设计规则的两种不同方式(检测像##<Text>##这样的标记)
Two Different Ways of Designing a Rule (Detecting Tokens Like ##<Text>##)
我正在为基于 markdown 的语言设计语法,但没有上下文感知。
例如,我想检测像## ## 这样的标记。
我发现了两种不同的设计规则的方法,但我不太确定哪种方法是最好的方法。
第一种方式:定义更复杂的标记和简单的规则。
fragment
HEAD
: '#'
;
fragment
HEADING_TEXT
: (~[#]|'\#')+?
;
SUBHEADLINE
: HEAD HEAD HEADING_TEXT HEAD HEAD
;
subheadline
: SUBHEADLINE
;
由于片段 HEAD 和 HEADING_TEXT 会到达解析器。我在 IntelliJ 中制作原型,解析效果很好。并且错误消息显示类似 "missing SUBHEADLINE" 什么对主应用程序有用(我想我可以轻松地将这些错误更改为人类可读的错误)。
第二种方法:更简单的标记和更复杂的解析器规则。
HEAD
: '#'
;
HEADING_TEXT
: (~[#]|'\#')+?
;
subheadline
: HEAD HEAD HEADING_TEXT HEAD HEAD
;
也很好用。错误更具体,可能不太适合将它们转换为人类可读的错误。
但我总体上不确定我应该遵循哪种方法以及为什么?!在这种情况下,更复杂的标记更容易编写,因为不会像普通编程语言那样包含任何复杂的规则。但感觉这不是正确的做法。
两种方式都有自己的行为,这取决于你需要什么来决定使用什么。以您所做的方式在词法分析器中定义副标题不允许 skipped/hidden 之间的标记。 '#',这可能是您想要的。在解析器中这样做允许例如# /*acomment*/headline##
这可能不是预期的行为。此外,我会将严格属于同一类的事物合并为一个规则。例如,您的第二个变体中的 HEADING_TEXT 可能会匹配您希望以不同方式匹配的输入。而是完全按照语言指示定义副标题:
SUBHEADING: '##' .*? '##';
这比你的更简单的变体更简洁,同时仍然不允许在标记之间跳过输入。
我正在为基于 markdown 的语言设计语法,但没有上下文感知。
例如,我想检测像## ## 这样的标记。
我发现了两种不同的设计规则的方法,但我不太确定哪种方法是最好的方法。
第一种方式:定义更复杂的标记和简单的规则。
fragment
HEAD
: '#'
;
fragment
HEADING_TEXT
: (~[#]|'\#')+?
;
SUBHEADLINE
: HEAD HEAD HEADING_TEXT HEAD HEAD
;
subheadline
: SUBHEADLINE
;
由于片段 HEAD 和 HEADING_TEXT 会到达解析器。我在 IntelliJ 中制作原型,解析效果很好。并且错误消息显示类似 "missing SUBHEADLINE" 什么对主应用程序有用(我想我可以轻松地将这些错误更改为人类可读的错误)。
第二种方法:更简单的标记和更复杂的解析器规则。
HEAD
: '#'
;
HEADING_TEXT
: (~[#]|'\#')+?
;
subheadline
: HEAD HEAD HEADING_TEXT HEAD HEAD
;
也很好用。错误更具体,可能不太适合将它们转换为人类可读的错误。
但我总体上不确定我应该遵循哪种方法以及为什么?!在这种情况下,更复杂的标记更容易编写,因为不会像普通编程语言那样包含任何复杂的规则。但感觉这不是正确的做法。
两种方式都有自己的行为,这取决于你需要什么来决定使用什么。以您所做的方式在词法分析器中定义副标题不允许 skipped/hidden 之间的标记。 '#',这可能是您想要的。在解析器中这样做允许例如# /*acomment*/headline##
这可能不是预期的行为。此外,我会将严格属于同一类的事物合并为一个规则。例如,您的第二个变体中的 HEADING_TEXT 可能会匹配您希望以不同方式匹配的输入。而是完全按照语言指示定义副标题:
SUBHEADING: '##' .*? '##';
这比你的更简单的变体更简洁,同时仍然不允许在标记之间跳过输入。