将括号解析为原子ANTLR

时间:2012-12-20 21:10:27

标签: parsing antlr grammar expression

我正在尝试匹配平衡括号,以便在匹配时创建PARAMS树,否则只需将LPARAM和RPARAM标记作为原子添加到树中...

tokens
{
    LIST;    
    PARAMS;
}

start   : list -> ^(LIST list);

list    : (expr|atom)+;

expr : LPARAM list? RPARAM -> ^(PARAMS list?);

atom :  INT | LPARAM | RPARAM;

INT :   '0'..'9'+;
LPARAM  :   '(';
RPARAM  :   ')';

目前,它永远不会创建PARAMS树,因为在规则expr中,它始终会将结束RPARAM视为原子,而不是该规则的结束标记。 / p>

所以目前,像1 2 3 (4) 5这样的东西被添加到LIST树中作为令牌的平面列表,而不是所需的分组。

我之前已经处理过将令牌作为原子添加到树中,但是他们永远无法启动另一个规则,正如LPARAM所做的那样。

我在这里需要某种合成/语义谓词吗?

1 个答案:

答案 0 :(得分:3)

这是一个带有几个约束的简单方法。我认为这些符合您在评论中提到的预期行为。

  • 儿童列表中不会出现不匹配的LPARAM
  • 儿童列表中不会出现不匹配的RPARAM

语法:

start   : root+ EOF -> ^(LIST root+ );

root    : expr
        | LPARAM
        | RPARAM
        ;

expr    : list
        | atom
        ;           

list    : LPARAM expr+ RPARAM -> ^(LIST expr+)
        ;

atom    : INT
        ;

规则root匹配不匹配的LPARAMRPARAM。规则listatom只关心自己。

此解决方案相对脆弱,因为规则root要求在exprLPARAM之前列出RPARAM。即便如此,也许这足以解决您的问题。

测试用例1:无列表

输入:1 2 3

输出:

1 2 3

测试用例2:一个列表

输入:1 (2) 3

输出:

1 (2) 3

测试用例3:两个列表

输入:(1) 2 (3)

输出:

(1) 2 (3)

测试案例4:没有列表,不匹配的左侧

输入:((1 2 3

输出:

((1 2 3

测试用例5:两个列表,不匹配的左侧

输入:((1 (2) (3)

输出:

((1 (2) (3)

测试案例6:没有列表,不匹配的权利

输入:1 2 3))

输出:

1 2 3))

测试案例7:两个列表,不匹配的权利

输入:(1) (2) 3))

输出:

(1) (2) 3))

测试用例8:两个列表,混合不匹配的左侧

输入:((1 (2) ( (3)

输出: ((1 (2) ( (3)

测试案例9:两个列表,混合不匹配的权利

输入:(1) ) (2) 3))

输出:

(1) ) (2) 3))


这是一个稍微复杂的语法,可以在[]()对上运行。我认为当你添加对时,解决方案会变得越来越糟,但嘿,这很有趣!您可能也会受到语法驱动AST构建的限制。

start   : root+ EOF -> ^(LIST root+ )
        ;

root    : expr
        | LPARAM
        | RPARAM
        | LSQB
        | RSQB
        ;       
expr    : plist
        | slist
        | atom
        ;           

plist   : LPARAM pexpr* RPARAM -> ^(LIST pexpr*)
        ;

pexpr   : slist
        | atom
        | LSQB
        | RSQB
        ;       

slist   : LSQB sexpr* RSQB -> ^(LIST sexpr*)
        ;

sexpr   : plist
        | atom
        | LPARAM
        | RPARAM
        ;               

atom    : INT;

INT     : ('0'..'9')+;
LPARAM  : '(';
RPARAM  : ')';
LSQB    : '[';
RSQB    : ']';