1

我正在尝试匹配平衡的括号,这样,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视为原子,而不是该规则的结束标记。

所以目前,类似的东西1 2 3 (4) 5被添加到LIST树中作为标记的平面列表,而不是所需的分组。

我之前处理过将标记作为原子添加到树中,但他们从来没有能够启动另一个规则,就像LPARAM这里一样。

我需要某种语法/语义谓词吗?

4

1 回答 1

3

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

  • 不匹配的LPARAM永远不会出现在子列表中
  • 不匹配的RPARAM永远不会出现在子列表中

语法:

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

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

atom    : INT
        ;

规则root匹配不匹配LPARAM的 s 和RPARAMs。规则listatom只关心自己。

该解决方案相对脆弱,因为 ruleroot需要在和expr之前列出。即便如此,也许这足以解决您的问题。LPARAMRPARAM

测试用例 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    : ']';
于 2012-12-20T23:14:44.027 回答