我试图用ANTLR解析几句话。我已经为此写了基本语法。
语法说每个句子都可以启动关键字'KEYWORDTYPE1'或'KEYWORDTYPE2' 每个句子以';'结尾。只有以“KEYWORDTYPE1”和“KEYWORDTYPE2”开头的句子之间的区别在于,对于第一个,我想要包含空格,而对于第二个,我想跳过所有空格。
grammar Hello;
options {
language = Java;
output = AST;
}
sentence
:
(
'KEYWORDTYPE1' swallow_to_semi_with_whitespace SEMI
| 'KEYWORDTYPE2' swallow_to_semi_remove_whitespace SEMI
)*
;
swallow_to_semi_with_whitespace : ~(SEMI )+ ;
swallow_to_semi_remove_whitespace : ~(SEMI )+ ;
SEMI :';' ;
ID : ( 'a'..'z' | 'A'..'Z' )+ ;
INT : '0'..'9'+;
NEWLINE :('\r'? '\n')*;
WS
:
( ' ' | '\t')
{
$channel = HIDDEN;
}
;
预期生成的树:
null
0 KEYWORDTYPE1
1
2 TRUE
3
4
5 111
6
7 FALSE
8
9 FALSE
10
11
12 FALSE
13
14 FALSE
15
16 ;
17 KEYWORDTYPE2
18 TRUE
19 TRUE
20 TRUE
21 TRUE
22 TRUE
23 TRUE
24 ;
但在两种情况下都使用当前的语法WHITESPACE。
你能否建议我应该做些什么改变?
答案 0 :(得分:1)
您的问题措辞不当但如果我理解,您希望将空格发送给解析器。如果是这样,请从WS中删除该操作。此外,这条规则将“无”作为错误的选项:
NEWLINE :('\r'? '\n')*;
答案 1 :(得分:-1)
我已经通过声明来改变语法以维持Lexer的状态
private boolean insideStatement = false;
然后在 KEYWORDTYPE1和SEMI Lexer中添加 @after ,将insideStatement分别更改为 true 和 false 。
最后的更改是WS Lexer规则更改为基于insideStatement发送到HIDDEN $ channel设置为true / false。
if (!insideStatement ) {
$channel = HIDDEN;
}
以下是完整的语法:
grammar Hello;
options {
language = Java;
output = AST;
}
@lexer::members {
private boolean insideStatement = false;
}
statement
:
(
KEYWORDTYPE1 swallow_to_semi SEMI
| KEYWORDTYPE2 swallow_to_semi SEMI
)*
;
KEYWORDTYPE1
@after {
insideStatement = true;
}
:
'KEYWORDTYPE1'
;
KEYWORDTYPE2
:
'KEYWORDTYPE2'
;
swallow_to_semi
:
~(SEMI )+
;
SEMI
@after {
insideStatement = false;
}
:
';'
;
ID
:
(
'a'..'z'
| 'A'..'Z'
)+
;
INT
:
'0'..'9'+
;
NEWLINE
:
('\r'? '\n')*
{
$channel = HIDDEN;
}
;
WS
:
(
' '
| '\t'
)
{
if (!insideStatement ) {
$channel = HIDDEN;
}
}
;