我有一个解析器,它接受两种不同类型的预定义HTML模板标记。一个明确地以"end*“结尾,而另一个则不是,例如:
{% for ... %}
An explicitly-terminated tag
{% endfor %}
{% assign x = 'my implicitly-terminated tag' %}这很好,但我也需要允许用户从C#代码中定义自己的标记,所以我需要Antlr4来匹配这些示例:
{% mycustomtag %}
...
{% endmycustomtag %}
{% myunterminatedtag %}我试图通过使用一个{% [USERDEFINED] %}语义谓词来匹配以{% end[USERDEFINED] %}结束标记以C#开头的任何内容,如下所示:
tag: // ...
| custom_blocktag
| custom_tag
// ...
// an explicitly-terminated tag
custom_blocktag: TAGSTART custom_block_start_tag customtagblock_expr* TAGEND custom_blocktag_block TAGSTART custom_block_end_tag TAGEND { _localctx.custom_block_end_tag().GetText().Equals("end" + _localctx.custom_block_start_tag().GetText()) }?;
// an implicitly-terminated tag
custom_tag: TAGSTART tagname customtag_expr* TAGEND ; 不幸的是,只有当我在显式结束之前没有隐式终止的标记时,它才能正确工作,但是如果它以相反的顺序发生,则会失败。
如果出现错误,这将失败:
{% xyz \"Test\" %}{% abc \"hello\"%}...{% endabc %}
但是,这样做很好:
{% abc \"hello\"%}...{% endabc %}{% xyz \"Test\" %}
据我理解,如果我希望语义谓词阻止匹配成功(而不是匹配规则,然后失败并生成错误),我需要左边的语义谓词。然而,如果语义谓词在左边的话,它就不会有任何值--所以我不知道如何继续。
是否有一种方法来编写解析器规则,以便我可以定义这两种情况?
发布于 2015-09-02 22:14:08
正如您已经描述过的问题,唯一可以从任何一个标记确定的语法确定性是,配对集的结束标记具有以' end‘开头的名称。在结束标记真正是语义关联之前就会出现一个开始标记( 'for‘-> 'endfor’关系可以用来确认关联,但在语法上并没有真正的帮助)。
最好的通用方法是处理解析器中的语法问题和解析树遍历器中的语义问题。在这里,检查每个标记并构建一个开始标记和结束标记关联表是很容易的。
因此,只需识别解析器中的标记,而不试图限定为开始、结束或单例。
tag: TBEG
( id expression // assign etc
| expression // for etc
| id // endfor etc
)
TEND // { processTag($tag); } // alternate solution
;实际上,通过向标记规则添加一个操作,您可以在解析器中实现相同的结果。此操作将创建并添加标记表中遇到的标记。当添加结束名标记时,前面的标记将被标记为开始标记。
如果您要实现其他游走者,可能需要实现标记表达式,则最好再添加一个以预先限定标记。
https://stackoverflow.com/questions/32338351
复制相似问题