- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
以下解析器规则的第二个选择 ((1-9)(0-9)) 在抽象语法树中产生两个节点。
oneToHundred
: ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')
| ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')
| '100'
;
(side node: 将数字“Lexing”到 Digit-Tokens 中对我不适用,因为有时像 2-4 这样的 0-9 的子范围可以代表某事. 与数字非常不同(顺便说一句,我无法影响)。)
所以对于 15,我得到两个节点 1 和 5,而不是 15,但我想将其作为一个节点表示的一个数字。
我无法在 token 级别使用词法分析器执行此操作,因为这取决于上下文,例如15 可能意味着两个截然不同的事物,要么是“一个符号和一个五个符号”(绝对应该是两个节点),要么是“十五”和 according to this post 上下文敏感应该留给解析器。
(编辑澄清:)
输入应该分开/用分号分隔
Input:
11;2102;34%;P11o
this would be split into four parts and
11 - would not be a number but one '1'-symbol and another '1'-symbol
2102 - would not be a number but: '2'-symbol '1'-symbol '0'-symbol '2'-symbol
34% - now here 34 would be the number thirtyfour
P11o: 'P'-symbol '1'-symbol '1'-symbol 'o'-symbol
在这四个 block 中,34% 将被解析器规则识别为百分比 block ,而其他 block 将被识别为符号 block 。所以 AST 应该看起来像这样:
SYMBOL
1
1
SYMBOL
2
1
0
2
PERCENT
34
SYMBOL
P
1
1
o
目标是 C#:
options {
language=CSharp3;
output=AST;
}
我是 Antlr 菜鸟,那么有没有一种好方法可以将这两个节点与解析器合并,或者我最好添加一个虚构的标记并在解析后在 C# 中“手动”连接两个数字?
最佳答案
您的解析器规则:
oneToHundred
: ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')
| ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')
| '100'
;
在幕后隐式创建以下 token :
D_1_9 : ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9');
D_0_9 : ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9');
D_100 : '100';
(不是那些规则名称,而是它们匹配的内容是创建的)
因此,如果您的词法分析器将获得输入 "11"
,则会创建两个 D_1_9
标记,并从 oneToHundred
规则将无法匹配(此替代方案需要两个标记:D_1_9 D_0_9
)。
您必须意识到词法分析器独立于解析器运行。解析器向词法分析器“询问”什么类型的标记并不重要:词法分析器有它自己的规则优先级导致 '1'|'2'|'3'|'4'|'5'|' 6'|'7'|'8'|'9'
永远不会被 D_0_9
规则匹配(因为它出现在之后 D_1_9
规则)。
让我们将您的输入称为 11;2102;34%;P11o
,四个单元由每个 atom
组成(其中一个 atom
是字母或数字)可能以 '%'
结尾:
unit
: atoms '%'?
;
如果它以 '%'
结尾,您只需使用重写规则创建一个以 PERCENT
为根的树,否则只需创建一个带有 的树SYMBOL
作为 root:
unit
: (atoms -> ^(/* SYMBOL */)) ('%' -> ^( /* PERCENT */))?
;
一个工作演示:
grammar T;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
ROOT;
SYMBOL;
PERCENT;
NUMBER;
}
parse
: unit (';' unit)* EOF -> ^(ROOT unit+)
;
unit
: (atoms -> ^(SYMBOL atoms))
('%' -> ^(PERCENT {new CommonTree(new CommonToken(NUMBER, $atoms.text))}))?
;
atoms
: atom+
;
atom
: Letter
| Digit
;
Digit : '0'..'9';
Letter : 'a'..'z' | 'A'..'Z';
您可以使用以下类测试解析器:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("11;2102;34%;P11o"));
TParser parser = new TParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
这将产生对应于以下 AST 的 DOT 输出:
在上图中,所有叶子的类型都是Letter
或Digit
,除了"34"
,它的类型是NUMBER
.
关于c# - 我如何在 ANTLR 中实现将两个节点合二为一的解析器规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8289762/
我是一名优秀的程序员,十分优秀!