Parsing ANTLR中的匹配括号

Parsing ANTLR中的匹配括号,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,我是Antlr的新手,最近遇到了一个括号匹配的问题。解析树中的每个节点的形式为(Node1,W1,W2,Node2),其中Node1和Node2是两个节点,W1和W2是它们之间的两个权重。给定一个输入文件为(1,C,10,2)。((2,P,2,3)。(3,S,3,2))*(2,T,2,4),解析树看起来是错误的,其中运算符不是这些节点的父节点,括号不匹配 我编写的解析文件如下所示: grammar Semi; prog : expr+ ; expr : exp

我是Antlr的新手,最近遇到了一个括号匹配的问题。解析树中的每个节点的形式为
(Node1,W1,W2,Node2)
,其中
Node1
Node2
是两个节点,
W1
W2
是它们之间的两个权重。给定一个输入文件为
(1,C,10,2)。((2,P,2,3)。(3,S,3,2))*(2,T,2,4)
,解析树看起来是错误的,其中运算符不是这些节点的父节点,括号不匹配

我编写的解析文件如下所示:

grammar Semi;

prog
    : expr+
    ;
    
expr
    : expr '*'   
    | expr ('.'|'+') expr 
    | tuple   
    | '(' expr ')' 
    ;

tuple
    : LP NODE W1 W2 NODE RP
    ;

LP  : '(' ;
RP  : ')' ;
W1  : [PCST0];
W2  : [0-9]+;
NODE: [0-9]+;


WS  : [ \t\r\n]+ -> skip ;    // toss out whitespace
COMMA: ',' -> skip;
似乎
expr |'('expr')”
无法正常工作。那么,我应该怎么做才能让这个解析器检测括号是否属于节点呢? 更新: 命令中有两个错误:

line 1:1 no viable alternative at input '(1'
line 1:13 no viable alternative at input '(2'

因此,lexer似乎没有检测到元组,但为什么呢?

您的W2和节点规则是相同的,因此您想要成为节点的节点与W2匹配

grun with-tokens选项:(注意,没有节点令牌)

为了更自由地使用语法,我建议您的Lexer规则应该以原始类型为中心。而且,您可以使用标签使各种元素或元组在代码中更容易访问。下面是一个例子:

grammar Semi;

prog: expr+;

expr: expr '*' | expr ('.' | '+') expr | tuple | LP expr RP;

tuple: LP nodef=INT COMMA w1=PCST0 COMMA w2=INT COMMA nodet=INT RP;

LP: '(';
RP: ')';
PCST0: [PCST0];
INT: [0-9]+;

COMMA: ',';
WS: [ \t\r\n]+ -> skip; // toss out whitespace

通过此更改,元组上下文类将具有w1、w1和节点的访问器。节点将是我在这里定义的NBR令牌数组。

我怀疑您的问题与
“('expr')”
产品无关,而是与您的词法规则有关。如果您查看为您的输入生成的标记,您可能会发现它们不是您所期望的。@sepp2k是的,我刚刚意识到这一点,但我不知道如何修复它。.我还发现一个错误“输入时没有可行的替代方案”(1')首先,在命令中,您不应该有多个与完全相同的模式匹配的lexer规则。这只会导致其中一个失效。然后,另一个问题是单个
0
本身将生成
W1
标记,但您可能也希望允许0作为W2或节点。最简单的解决方案可能是只为
'0'
使用专用的lexer规则,它可以在
W1
W2
或节点可以使用的任何地方使用。@sepp2k omg非常感谢!我只是尝试对数字使用一个lexer,现在它工作得很好。我还有一个关于你的回答的问题,如果我使用逗号作为分隔符,这个问题可以吗可以避免0问题吗?在输出解析树中似乎是这样,但我不确定。0的问题是输入,例如
(0,0,0,0)
,根据我对您的格式的理解,它应该是有效的,将被翻译为
LP W1 W1 W1 RP
,这与您的
元组规则不匹配。现在您可以更改元组以允许
W1
无处不在,但随后
(P,P,P)
也是允许的,我相信您不希望这样。所以我建议更改它,使
0 12 P
变为
0个W1字母
。然后您可以定义
w2
节点
(作为语法规则,而不是词法规则)作为
ZERO | NUMBER
,您可以将
w1
定义为
ZERO | w1|u字母
。感谢您的详细解释,现在我觉得这对我来说更清楚了!关于您更新的语法,我还有一个问题,因为我需要为不同的访问者检索w1和w2的值,如果我再添加一个la,有意义吗语法中的yer?比如
tuple:LP nodef wc wd nodet RP;nodef:INT;wc:W1;wd:INT;nodet:INT;
,其中INT是数字。所以在这种情况下,我不会在这里使用多个w2。问得好。在解析器规则中使用标签是一种非常简单的方法,可以在没有其他级别规则的情况下获得所需的内容(规则级别很容易失控,让导航变得痛苦。我编辑了我的答案,以展示您是如何做到这一点的。
grammar Semi;

prog: expr+;

expr: expr '*' | expr ('.' | '+') expr | tuple | LP expr RP;

tuple: LP W2 COMMA W1 COMMA W2 COMMA W2 RP;

LP: '(';
RP: ')';
W1: [PCST0];
W2: [0-9]+;
NODE: [0-9]+;

WS: [ \t\r\n]+ -> skip; // toss out whitespace
COMMA: ',';
grammar Semi;

prog: expr+;

expr: expr '*' | expr ('.' | '+') expr | tuple | LP expr RP;

tuple: LP nodef=INT COMMA w1=PCST0 COMMA w2=INT COMMA nodet=INT RP;

LP: '(';
RP: ')';
PCST0: [PCST0];
INT: [0-9]+;

COMMA: ',';
WS: [ \t\r\n]+ -> skip; // toss out whitespace