Tree 识别ANTLR4中文本说明节点深度的树
我试图解析一些描述树的输入文本 为了更好地解释这个问题,我不是从文本开始,而是从预期的结果开始: 此树可以编写为带括号的表达式(例如): 使用ANTLR4很容易识别:Tree 识别ANTLR4中文本说明节点深度的树,tree,antlr4,Tree,Antlr4,我试图解析一些描述树的输入文本 为了更好地解释这个问题,我不是从文本开始,而是从预期的结果开始: 此树可以编写为带括号的表达式(例如): 使用ANTLR4很容易识别: grammar ParenthesizedDepthGrammar; WS : (' '|'\n') -> channel(HIDDEN); TEXT : [-A-Za-z0-9]+; root: item*; item: TEXT ('(' item+ ')')? ; 现在的问题是,我的输入将树
grammar ParenthesizedDepthGrammar;
WS : (' '|'\n') -> channel(HIDDEN);
TEXT : [-A-Za-z0-9]+;
root: item*;
item:
TEXT ('(' item+ ')')?
;
现在的问题是,我的输入将树描述为括号内的表达式。取而代之的是,每个节点都有一个数字,表示其深度,它隐式地属于最近的前一个深度较浅的节点。像这样:
1 node-0
2 node-00
3 node-000
3 node-001
3 node-002
2 node-01
3 node-010
4 node-0100
3 node-011
2 node-02
1 node-1
2 node-10
我认为以下语法可以正确识别它:
grammar TextualDepthGrammar;
WS : (' '|'\n') -> channel(HIDDEN);
LEVEL : [0-9]+;
TEXT : [-A-Za-z0-9]+;
root: item[0]*;
item[int parentLevel] returns [int level]:
LEVEL
{ $level = $LEVEL.int; }
{ $level > $parentLevel }?
TEXT
item[$level]*
;
但事实并非如此
语义谓词{$level>$parentLevel}?
正确地切断了解析,但是level
已经被使用,并且祖父母树节点没有机会尝试解析新的子节点
我认为它需要:
级别“取消使用”;或
项目开始时提前阅读级别
,如果不比父级深,则进行规则和保释
但是如何解决呢?我可以使用
getCurrentToken()
查看(readahead)下一个标记来解决这个问题:
grammar TextualDepthGrammar;
WS : (' '|'\n') -> channel(HIDDEN);
LEVEL : [0-9]+;
TEXT : [-A-Za-z0-9]+;
root: item*;
item:
LEVEL
TEXT
(
{ Integer.parseInt(getCurrentToken().getText()) > $LEVEL.int }?
item
)*
;
对于输入:
1 node-0
2 node-00
3 node-000
3 node-001
3 node-002
2 node-01
3 node-010
4 node-0100
3 node-011
2 node-02
1 node-1
2 node-10
它正确地给出了:
(root
(item 1 node-0
(item 2 node-00
(item 3 node-000)
(item 3 node-001)
(item 3 node-002)
)
(item 2 node-01
(item 3 node-010
(item 4 node-0100)
)
(item 3 node-011)
)
(item 2 node-02)
)
(item 1 node-1
(item 2 node-10)
)
)
尽管我发现使用getCurrentToken()
有点不太正式。
如果决定取决于另一个令牌怎么办?
如果从当前令牌到要做出决定的令牌之间存在可选令牌,该怎么办?确保已修复所有语法生成错误和警告,或者确保它们无关紧要。
TEXT
规则应给出不完整的范围警告。要在集合中包含文字连字符,它必须是最后一个元素
TEXT : [A-Za-z0-9-]+;
为了确保解析器考虑所有输入,您需要确定地匹配EOF令牌
root: item* EOF;
按照Antlr的工作方式,lexer将在计算第一个解析器规则之前使用所有输入。解析器没有简单(或预期)的方法来控制词法分析器的操作
做您似乎要做的事情的惯用方法是解析并生成整个输入文本的树。在树漫游器中,您可以分析受任意选定约束集约束的树。多个Walker可用于不同的约束集,而无需重新生成树。文本lexer规则(开头带有连字符)运行良好。没有错误,没有警告。我只是习惯于用这种方式匹配字符类内部的连字符,因为其他一些实现(vi?grep?sed?我不知道)需要它。作为你的第二个技巧,我认为我最好使用我之前发布的答案(使用
getCurrentToken()
),至少在我遇到类似于我在最后提出的问题的情况之前。对它进行一次解析,然后在树上行走以更正它似乎是在浪费ANTLR4的能力。
root: item* EOF;