ANTLR4 grun rig 似乎没有正确报告令牌……我明白吗?
ANTLR4 grun rig doesn't appear to report tokens properly... do I understand this?
我正在用 grun 测试一些语法,但我没有看到我的标记被识别为标记。我最初以为我可能基于这个 创建了 "implicit" 个令牌。
此外,在查看 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]
None 我的令牌被识别为令牌。
我期待:
[@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]
在我的预期结果中,我用 TOKEN NAME 替换了 'chars'。
I 运行 antlr4 with -Xlog 和我的令牌已声明(倒数第二行),所以现在我想知道我是否只是误解了 grun 日志报告的内容。我希望 <> 中的数据是词法分析器传递的令牌名称。我的理解有误吗?
我可以对我的语法做些什么来让标记被识别为标记?
或者...如何调试语法以确保词法分析器正确识别标记?
这是我的 -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
我仍在挖掘和 运行 实验。希望这个问题和任何答案都会对其他人有所帮助。
这并不完美。 grun output 仍然没有输出我的标记..但我可以通过插入 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 规则正在被发现,而且我有 analysis/debug 的技术。我想 understand/decipher grun more 我将不得不更多地研究来源...这导致想要 "build/test" 修改 antlr,这是一个滑坡。我正在努力专注于我原来的任务......
正在开发解析器。
我也很惊讶。在以前的版本中,令牌的名称甚至没有翻译:
[@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 脚本,通过获取 <grammar>.tokens
文件将 <n>
翻译成它的名字。现在在 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]
我正在用 grun 测试一些语法,但我没有看到我的标记被识别为标记。我最初以为我可能基于这个
此外,在查看 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]
None 我的令牌被识别为令牌。 我期待:
[@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]
在我的预期结果中,我用 TOKEN NAME 替换了 'chars'。
I 运行 antlr4 with -Xlog 和我的令牌已声明(倒数第二行),所以现在我想知道我是否只是误解了 grun 日志报告的内容。我希望 <> 中的数据是词法分析器传递的令牌名称。我的理解有误吗?
我可以对我的语法做些什么来让标记被识别为标记? 或者...如何调试语法以确保词法分析器正确识别标记?
这是我的 -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
我仍在挖掘和 运行 实验。希望这个问题和任何答案都会对其他人有所帮助。
这并不完美。 grun output 仍然没有输出我的标记..但我可以通过插入 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 规则正在被发现,而且我有 analysis/debug 的技术。我想 understand/decipher grun more 我将不得不更多地研究来源...这导致想要 "build/test" 修改 antlr,这是一个滑坡。我正在努力专注于我原来的任务...... 正在开发解析器。
我也很惊讶。在以前的版本中,令牌的名称甚至没有翻译:
[@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 脚本,通过获取 <grammar>.tokens
文件将 <n>
翻译成它的名字。现在在 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]