使用ANTLR C目标,如何在Lexer中获取先前匹配的令牌?

时间:2010-07-19 03:45:17

标签: c antlr

我有一个相对复杂的词法问题。鉴于以下输入:

-argument -argument#with hashed data# #plainhashedData#

我需要这些代币:

ARGUMENT (Text = "argument")
ARGUMENT (Text = "argument")
EXTRADATA (Text = "with hashed data")
OTHER (Text = "#plainhasheddata#")

我已经能够处理文本操作问题了,但是我需要一些方法来指定只有先前匹配的规则是ARGUMENT才能匹配EXTRADATA规则。 ANTLR支持语法谓词​​(即使在词法分析器中),所以这应该不难实现 - 但我需要能够在我能够编写这样的谓词之前获得先前匹配的令牌。

这是否可以使用ANTLR C代码生成目标?

Billy3

编辑:当前的词法规则看起来像:

ARGUMENT : '-'+ (~('-'|'#'|' '))+
         ;
EXTRADATA : '#' (~'#')* '#'
          ;
OTHER : ~'-' (~' ')*
      ;

1 个答案:

答案 0 :(得分:1)

注意,我对C语言知之甚少,并且对ANTLR的C运行时没有经验,但是我的示例中的Java代码不应该太难以重写为C.


您可以通过覆盖基础emit(Token)类中的Lexer方法并跟踪您的词法分析器进程的最后Token来实现此目的:

private Token last;

@Override
public void emit(Token token) {
  last = token;
  super.emit(token);
}

要将其包含在词法分析器中,请在以下语法之间添加语法:

@lexer::members {

  // your code here

}

现在,您必须先将Other规则置于之前的<{1}}规则中,然后在ExtraData规则之前添加gated semantic predicate,以检查{ {1}}令牌是Other令牌:

last

其中ExtraData方法是Other : {behind(ExtraData)}?=> ~'-' (~' ')* ; 部分中的自定义方法:

behind(int)

如果最后一个令牌是@lexer::members { ... },则会导致protected boolean behind(int tokenType) { return last != null && last.getType() == tokenType; } 令牌仅与匹配

一点点的演示语法:

Other

和一个测试它的主类:

ExtraData

首先从语法中生成一个解析器和词法分析器:

java -cp antlr-3.2.jar org.antlr.Tool LookBehind.g 

然后编译所有grammar LookBehind; @lexer::members { private Token last; @Override public void emit(Token token) { last = token; super.emit(token); } protected boolean behind(int tokenType) { return last != null && last.getType() == tokenType; } } parse : token+ EOF ; token : Argument {System.out.println("Argument :: "+$Argument.text);} | Other {System.out.println("Other :: "+$Other.text);} | ExtraData {System.out.println("ExtraData :: "+$ExtraData.text);} ; Argument : '-'+ (~('-' | '#' | ' '))+ ; Other : {behind(ExtraData)}?=> ~('-' | ' ') (~' ')* ; ExtraData : '#' (~'#')* '#' ; Space : (' ' | '\t' | '\r' | '\n') {skip();} ; 个文件:

javac -cp antlr-3.2.jar *.java

最后运行主类:

java -cp .:antlr-3.2.jar Main

(在Windows上执行:import org.antlr.runtime.*; public class Main { public static void main(String[] args) throws Exception { String source = "-argument -argument#with hashed data# #plainhashedData#"; ANTLRStringStream in = new ANTLRStringStream(source); LookBehindLexer lexer = new LookBehindLexer(in); CommonTokenStream tokens = new CommonTokenStream(lexer); LookBehindParser parser = new LookBehindParser(tokens); parser.parse(); } }

然后将产生以下输出:

Argument  :: -argument
Argument  :: -argument
ExtraData :: #with hashed data#
Other     :: #plainhashedData#

修改

正如你(Billy)在你的评论中提到的,在C中你无法覆盖方法。您还可以在每个词法分析器规则的.java子句中设置一个布尔标志,以跟踪最后一个标记是java -cp .;antlr-3.2.jar Main的时间并在谓词中使用该标志:

@after{ ... }

虽然这有点像黑客攻击:在每个词法分析器规则中你都必须设置标志。

您也可以向ANTLR mailing-list发帖提问:除了许多ANTLR专家外,维持ANTLR C运行时的人经常光顾那里。

祝你好运!