Java ';标识符';规则还使用ANTLR Lexer语法中的关键字
在使用Antlr 3.5语法进行Java解析时,注意到“标识符”规则在Antlr Lexer语法中使用的关键字很少。词法语法是Java ';标识符';规则还使用ANTLR Lexer语法中的关键字,java,parsing,antlr,tokenize,antlr3,Java,Parsing,Antlr,Tokenize,Antlr3,在使用Antlr 3.5语法进行Java解析时,注意到“标识符”规则在Antlr Lexer语法中使用的关键字很少。词法语法是 lexer grammar JavaLexer; options { //k=8; language=Java; filter=true; //backtrack=true; } @lexer::header { package java; } @lexer::members { public ArrayList<String>
lexer grammar JavaLexer;
options {
//k=8;
language=Java;
filter=true;
//backtrack=true;
}
@lexer::header {
package java;
}
@lexer::members {
public ArrayList<String> keywordsList = new ArrayList<String>();
}
V_DECLARATION
:
( ((MODIFIERS)=>tok1=MODIFIERS WS+)? tok2=TYPE WS+ var=V_DECLARATOR WS* )
{...};
fragment
V_DECLARATOR
:
(
tok=IDENTIFIER WS* ( ',' | ';' | ASSIGN WS* V_VALUE )
)
{...};
fragment
V_VALUE
: (IDENTIFIER (DOT WS* IDENTIFIER WS* '(' | ',' | ';'))
;
MODIFIERS
:
(PUBLIC | PRIVATE | FINAL)+
;
PRIVATE
: tok = 'private'
{ keywordsList.add($tok.getText()); }
;
PUBLIC
: tok = 'public'
{ keywordsList.add($tok.getText()); }
;
DOT
: '.'
{ keywordsList.add("."); }
;
THIS
: tok = 'this'
{ keywordsList.add($tok.getText()); }
;
ASSIGN
: '='
{ keywordsList.add("="); }
;
IDENTIFIER:
tok =Identifier
{
//System.out.println("Identifier: " + $tok.text);
}
;
fragment
Identifier
: (Letter (Letter|JavaIDDigit)*);
fragment
Letter
: '\u0024' |
'\u0041'..'\u005a' |
'\u005f' |
'\u0061'..'\u007a' |
'\u00c0'..'\u00d6' |
'\u00d8'..'\u00f6' |
'\u00f8'..'\u00ff' |
'\u0100'..'\u1fff' |
'\u3040'..'\u318f' |
'\u3300'..'\u337f' |
'\u3400'..'\u3d2d' |
'\u4e00'..'\u9fff' |
'\uf900'..'\ufaff'
;
fragment
JavaIDDigit
: '\u0030'..'\u0039' |
'\u0660'..'\u0669' |
'\u06f0'..'\u06f9' |
'\u0966'..'\u096f' |
'\u09e6'..'\u09ef' |
'\u0a66'..'\u0a6f' |
'\u0ae6'..'\u0aef' |
'\u0b66'..'\u0b6f' |
'\u0be7'..'\u0bef' |
'\u0c66'..'\u0c6f' |
'\u0ce6'..'\u0cef' |
'\u0d66'..'\u0d6f' |
'\u0e50'..'\u0e59' |
'\u0ed0'..'\u0ed9' |
'\u1040'..'\u1049'
;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN; skip();}
;
然后规则“VAR_VALUE->IDENTIFIER”也会使用“this”关键字,这是不可取的,因为关键字也会被收集到一个单独的列表中
Antlr语法中是否有任何技巧/规定,在不影响其他功能(如“标识符”)的情况下自行匹配关键字规则?您的问题确实是由于对lexer中的内容和parser中的内容的误解造成的:
- Lexer的工作是确定字符流代表哪些单词
- e、 g.
是一个this
,this
是一个0
,数字
是一个
标识符
- e、 g.
- 解析器的工作是确定lexer发出的单词序列是否符合给定的语言,也就是说,由这些单词组成的“句子”是否有意义
- e、 该声明由可能的修饰符、类型和标识符列表组成
由于lexer的工作是确定输入中有哪些单词,因此它会处理输入并查找最长有效匹配(在ANTLR中,如果两个或多个规则接受相同的输入,则源语法中最高的规则获胜)。不是针对任何“最具体的”,而是最长的 例如:
- 输入
t
- 可以是
或此
标识符
- 可以是
- 输入
h
- 仍然可以是
或此
标识符
- 仍然可以是
- 输入
a
- 不能再是
,只能是此
标识符
- 不能再是
- 输入
t
确定标识符
- 输入
- 不再匹配
,因此标识符
匹配为将
,最后一个输入将匹配为下一个令牌的新开始标识符
- 不再匹配
- 输入
,t
,h
,i
s
- 可以始终作为
或此
标识符进行匹配
- 可以始终作为
- 输入
- 不能再被任何东西匹配,因此
将被匹配为此
(最顶端的匹配规则),而不是此
,并且标识符
将启动一个新令牌
- 不能再被任何东西匹配,因此
此
确实可以通过标识符
规则进行匹配,因此整个声明符合V_声明
词法规则-因此,除非有另一个词法规则至少可以匹配相同长度的输入,并且在语法中早于此规则,否则将应用此规则
您没有提供任何引用此规则的规则,因此我们不知道这在语法中的具体效果如何,但明显的原因是lexer可以比使用此规则的任何东西匹配更长的输入或更早的规则。还尝试了选项
{backtrack=true;}
,但是没有结果。我认为规则V_声明、V_声明符和V_值属于解析器,而不是词法分析器。不@Maurice Perry,这些是非常基本的词法分析器规则,用于匹配特定的标记,然后触发包含各种规则中完整Java语法的解析器。噢!还有修饰符,修饰符之间不应该有WSs吗?
public final int inch = this.getValue();