ANTLR4 grun rig似乎没有正确报告令牌......我明白这一点吗?

时间:2017-01-19 20:42:37

标签: antlr antlr4

我正在用grun测试一些语法,而且我没有看到我的令牌被识别为令牌。我最初认为也许我创造了"隐含"基于此StackOverflow link的令牌。

另外,在审查grun -tokens的输出时,我发现了以下链接: 1)最近的Change到-tokens输出。 2)可能已过时testrig.md我分叉了这个并且正在挖掘它。

这是我的简单HelloTC.g4,我在此探讨:

grammar HelloTC;
r  : HELLO id; 
WS : [ \r\t\n]+ -> skip ;
CMD: '%';
DIR: '%%';
A:   'A'; 
AA:  'AA';
HELLO:'hello';
ID : [a-z]+ ;
id :  DIR | CMD | A | AA;

我用以下方法测试:

grun HelloTC r -tokens
hello %%
hello %
hello A
hello AA
^Z

[@0,0:4='hello',<'hello'>,1:0]
[@1,6:7='%%',<'%%'>,1:6]
[@2,10:14='hello',<'hello'>,2:0]
[@3,16:16='%',<'%'>,2:6]
[@4,19:23='hello',<'hello'>,3:0]
[@5,25:25='A',<'A'>,3:6]
[@6,28:32='hello',<'hello'>,4:0]
[@7,34:35='AA',<'AA'>,4:6]
[@8,38:37='<EOF>',<EOF>,5:0]

我的所有令牌均未被识别为令牌。 我在期待:

[@0,0:4='hello',<HELLO>,1:0]
[@1,6:7='%%',<DIR>,1:6]
[@2,10:14='hello',<HELLO>,2:0]
[@3,16:16='%',<CMD>,2:6]
[@4,19:23='hello',<HELLO>,3:0]
[@5,25:25='A',<A>,3:6]
[@6,28:32='hello',<HELLO>,4:0]
[@7,34:35='AA',<AA>,4:6]
[@8,38:37='<EOF>',<EOF>,5:0]

在我的预期结果中,我取代了#chars&#39;与TOKEN NAME。

我用-Xlog运行了antlr4并且声明了我的令牌(倒数第二行),所以现在我想知道我是否只是误解了grun日志报告的内容。我期望&lt;&gt;中的数据成为词法分析器传递的TOKEN名称。我不正确吗?

我可以对语法做些什么才能让令牌被识别为令牌? 或者......如何调试语法以确保词法分析器正确识别标记?

这是我的-Xlog文件:

2017-01-20 06:57:29:640 grammar LogManager.java:25 before: (COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello'))) (RULE id (BLOCK (ALT DIR) (ALT CMD) (ALT A) (ALT AA)))))
2017-01-20 06:57:29:661 grammar LogManager.java:25 after: (COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello'))) (RULE id (BLOCK (ALT (SET DIR CMD A AA))))))
2017-01-20 06:57:29:694 grammar LogManager.java:25 after extract implicit lexer =(COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE id (BLOCK (ALT (SET DIR CMD A AA))))))
2017-01-20 06:57:29:694 grammar LogManager.java:25 lexer =(LEXER_GRAMMAR HelloTCLexer (RULES (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello')))))
2017-01-20 06:57:30:040 semantics LogManager.java:25 tokens={EOF=-1, WS=1, CMD=2, DIR=3, A=4, AA=5, HELLO=6}
2017-01-20 06:57:30:040 semantics LogManager.java:25 strings={'%cat'=2, '%%'=3, 'A'=4, 'AA'=5, 'hello'=6}

我尝试创建语法的语法类型示例如下。

//COMMENTS
;comments
%%DIRECTIVEA
%%DIRECTIVEB
RESERVED_TOKEN(ARGS,ARGS)
%commandA
 commandB
 commandD
 commandE
 ...
 CommandH  (only A-H allowed)
// comments
%commandB
%%DIRECTIVEB
%commandD
 commandE
%commandA
 done

我还在挖掘和运行实验。希望这个问题,以及任何答案都会有所帮助。

2 个答案:

答案 0 :(得分:1)

我也很惊讶。在以前的版本中,甚至没有翻译令牌的名称:

[@0,0:4='hello',<6>,1:0]
[@1,6:7='%%',<3>,1:6]
[@2,9:13='hello',<6>,2:0]
[@3,15:15='%',<2>,2:6]
[@4,17:21='hello',<6>,3:0]
[@5,23:23='A',<4>,3:6]
[@6,25:29='hello',<6>,4:0]
[@7,31:32='AA',<5>,4:6]
[@8,34:33='<EOF>',<-1>,5:0]

多年前,我编写了一个Ruby脚本,通过获取<n>文件将<grammar>.tokens转换为其名称。它现在在4.6中完成。

如果您按照以下顺序定义HELLO和ID:

HELLO
    : [a-z]+ {getText().equals("hello")}? ;
ID  : [a-z]+ ;

使用此输入

    hello %%
...
    hello xyz

你有这个结果:

    [@0,0:4='hello',<HELLO>,1:0]
    [@1,6:7='%%',<'%%'>,1:6]
...
    [@8,34:38='hello',<HELLO>,5:0]
    [@9,40:42='xyz',<ID>,5:6]

输入hello不明确,可以通过两个规则进行匹配。词法分析器规则中的句法谓词允许词法分析器在输入为HELLO时选择hello

我们可以得出结论,常量由它们自己表示,而其他输入由令牌名称表示。尽管有这种好奇心,你的令牌仍然被正确识别。如果不是这样的话,解析器会抱怨: 输入hello %% 123给出:

$ grun Question r -tokens data.txt 
line 1:9 token recognition error at: '1'
line 1:10 token recognition error at: '2'
line 1:11 token recognition error at: '3'
[@0,0:4='hello',<HELLO>,1:0]
[@1,6:7='%%',<'%%'>,1:6]

如果在语法中添加INT规则

INT : [0-9]+ ;

然后识别新令牌:

[@0,0:4='hello',<HELLO>,1:0]
[@1,6:7='%%',<'%%'>,1:6]
[@2,9:11='123',<INT>,1:9]

答案 1 :(得分:0)

这并不完美。 grun输出仍然不输出我的标记..但我可以通过插入System.out.printlin()动作继续学习Java。 缺点是,在我完成之后,我必须将这些调试条款拉出来。 最终我的目标解析器将基于python。但我仍然在Java的学习曲线上。

link显示了如何使用操作进行调试。

有了这个,我将我的HelloTC.gr修改为:

grammar HelloTC;
r  : HELLO id+ {System.out.println("r rule encountered");};
WS : [ \r\t\n]+ -> skip ;
CMD: '%' {System.out.println("Lexer found a CMD");};
DIR: '%%'{System.out.println("Lexer found a DIR");};
A:   'A';
AA:  'AA';
HELLO:'hello'{System.out.println("Lexer found a HELLO");};
ID : [a-z]+ ;
id :  DIR | CMD | A | AA { System.out.println("Parser found rule match "+$text);};

用grun产量调试它:

java org.antlr.v4.gui.TestRig HelloTC r -tokens
hello%%
hello %%
^Z
Lexer found a HELLO
Lexer found a DIR
Lexer found a HELLO
Lexer found a DIR
[@0,0:4='hello',<'hello'>,1:0]
[@1,5:6='%%',<'%%'>,1:5]
[@2,9:13='hello',<'hello'>,2:0]
[@3,15:16='%%',<'%%'>,2:6]
[@4,19:18='<EOF>',<EOF>,3:0]
line 2:0 extraneous input 'hello' expecting {<EOF>, '%', '%%', 'A', 'AA'}
r rule encountered

所以好消息是Lexer规则正在被看到,我有一种分析/调试技术。我认为理解/破译更多我将不得不更多地查看来源......这导致想要“建立/测试”对antlr的修改,这是一个滑坡。我正在努力专注于我原来的任务...... 正在开发一个解析器。