我正在尝试匹配平衡括号,以便在匹配时创建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
所做的那样。
我在这里需要某种合成/语义谓词吗?
答案 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
匹配不匹配的LPARAM
和RPARAM
。规则list
和atom
只关心自己。
此解决方案相对脆弱,因为规则root
要求在expr
和LPARAM
之前列出RPARAM
。即便如此,也许这足以解决您的问题。
输入:1 2 3
输出:
输入:1 (2) 3
输出:
输入:(1) 2 (3)
输出:
输入:((1 2 3
输出:
输入:((1 (2) (3)
输出:
输入:1 2 3))
输出:
输入:(1) (2) 3))
输出:
输入:((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 : ']';