设计规则的两种不同方法(检测 ##<Text>## 等令牌)



我正在为一种基于markdown的语言设计语法,但没有上下文意识。

例如,我想检测像####这样的令牌。

我找到了两种不同的方法来设计规则,我不太确定哪种方法可能是最好的方法。

第一种方法:定义更复杂的令牌和一个简单的规则。

fragment
HEAD
: '#'
;
fragment
HEADING_TEXT
: (~[#]|'\#')+?
;
SUBHEADLINE
: HEAD HEAD HEADING_TEXT HEAD HEAD
;

subheadline
: SUBHEADLINE
;

由于碎片HEAD和HEADING_TEXT将到达解析器。我正在IntelliJ中进行原型设计,解析效果很好。错误消息显示了类似"缺少SUBHEADLINE"的内容,这对主应用程序来说很好(我认为我可以很容易地将这些错误更改为可读错误)。

第二种方法:解析器使用更简单的令牌和更复杂的规则。

HEAD
: '#'
;
HEADING_TEXT
: (~[#]|'\#')+?
;

subheadline
: HEAD HEAD HEADING_TEXT HEAD HEAD
;

效果也不错。这些错误更具体,可能不太适合将它们转换为人类可读的错误。

但总的来说,我不确定我应该遵循哪种方法,为什么?!在这种情况下,更复杂的令牌更容易编写,因为不会像普通编程语言那样包含任何复杂的规则。但感觉这不是正确的做法

这两种方式都有自己的行为,这取决于您需要决定使用什么。以您以前的方式定义lexer中的子标题行不允许在例如"#"之间跳过/隐藏标记,这可能是您想要的。相反,在解析器中这样做允许具有例如# /*acomment*/headline##,这可能不是预期的行为。此外,我会把严格属于一起的东西组合成一条规则。例如,第二个变体中的HEADING_TEXT可能会匹配您希望以不同方式匹配的输入。相反,按照语言的要求定义副标题:

SUBHEADING: '##' .*? '##';

这甚至比更简单的变体更简洁,同时仍然不允许在标记之间跳过输入。

相关内容

  • 没有找到相关文章

最新更新