如果解析器和词法分析器位于不同的包中,它们如何协同工作?

How can a parser and a lexer work together if they're in separate packages?

这个问题与 Antlr 有关,parser/lexer 生成器(在我看来非常棒)。具体来说,有问题的版本是 Antlr4。目前我正在尝试在单独的文件中创建一个 parser/lexer 组合,一开始效果很好。

但是,当我尝试将不同的组件模块化以方便组织时,我发现了一个问题。我用来模块化的两个工具,headers 中的包声明和设置解析器的标记词汇,分别完美地工作,但我似乎无法让它们很好地协同工作。

我整理了一个非常简短的示例来说明我的问题。

首先,我定义了词法分析器:

lexer grammar UsefulLexer;

@header{
package org.useful.lexer;
}

USEFUL_TOKEN:'I\'m useful, I promise!';

其次我定义了我的解析器。

parser grammar UsefulParser;

@header{
package org.useful.parser;
}

options{
    tokenVocab=UsefulLexer;
}

usefulRule:USEFUL_TOKEN*;

但是当我构建时,我得到了有用的错误:

cannot find tokens file /Users/me/Desktop/Workspace/Project_Name/src-gen/org/useful/parser/UsefulLexer.tokens

所有规则在组合语法中完美地协同工作,或者甚至单独地工作,前提是它们在同一个包中。然而,对于我如何使用 Antlr,多个解析器共享同一个词法分析器,将所有组件放在同一个包中首先违背了使用包的目的。

我已经查阅了 docs, especially the section on grammar structure,但找不到关于如何解决此问题的官方来源。我也尝试了明显的解决方案,将 tokenVocab=UsefulLexer 更改为 tokenVocab=org.useful.lexer.UsefulLexer,但这甚至无法解析。 (我觉得这有点讽刺。)

我缺少什么语法?或者这只是没有语法的东西?

必须构建词法分析器和解析器。这是一个简单的测试平台构建器:

@echo off
rem Execute the Antlr compiler/generator tool
rem put grammar files in "D:/DevFiles/Java/src/test/parser"

SETLOCAL

set files=../UsefulLexer.g4 ../UsefulParser.g4

set CLASSPATH=D:/DevFiles/Java/lib/antlr-4.5-complete.jar
set tool=org.antlr.v4.Tool

set cmd="C:/Program Files/Java/jre7/bin/java.exe" 
set opts=-visitor

cd /d D:/DevFiles/Java/src/test/parser/gen
%cmd% %tool% %opts% %files%

ENDLOCAL

pause
rem timeout 5

为了解决这个问题,我不得不为词法分析器和解析器修改我的 ANTLR 构建命令,添加 -lib 和 -package 选项。一旦我在我的解析器构建脚本中将 -lib 指向我的词法分析器的包,并将我的包声明移动到两个构建命令中,它就一帆风顺了。

希望这对其他人有帮助!