ANTLR 语法错误取决于定义规则的位置
ANTLR syntax error depending on where a rule is defined
我是解析和 ANTLR 的新手,如果这是一个愚蠢的问题,请提前致歉。我正在尝试使用 ANTLR 来解析逻辑公式(涉及 AND、OR、NOT)。我有以下语法
grammar LTL;
ltl: ltl_or | ltl_and | ltl_not | Atom;
ltl_and: OPEN_CURLY ltl CLOSE_CURLY And OPEN_CURLY ltl CLOSE_CURLY;
ltl_or: OPEN_CURLY ltl CLOSE_CURLY Or OPEN_CURLY ltl CLOSE_CURLY;
ltl_not: Not OPEN_CURLY ltl CLOSE_CURLY;
Or: 'Or' | 'or';
Atom: (~('{' | '}'))+;
And: 'And' | 'and';
Not: 'Not' | 'not';
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
我的测试用例是 {ABCD()}Or{AB CD()}
,我希望它应该被解析为具有两个原子的有效 Or
公式。上面的语法确实会发生这种情况。但是,如果我交换 Or
规则和 Atom
规则的位置,如下所示:
Atom: (~('{' | '}'))+;
Or: 'Or' | 'or';
我收到错误
line 1:8 no viable alternative at input '{ABCD()}Or'
有人可以指点一下吗?
这是您的语法的重构版本,可以正确处理您提供的输入,并利用其他 ANTLR 习语(希望)使其更易于阅读和维护。 (附有说明进行了哪些更改的注释。)
grammar LTL
;
// *almost* always a good idea to have a start rule that
// consumes everything up to EOF to prevent
// premature termination of parsing input
ltl_start: ltl EOF;
// *IF* you really want to allow a "naked" ATOM
// ltl_start: (ltl | ATOM) EOF;
// since it seems ltls are always wrapped in curlies,
// I've refactored them a bit to simplify also
// used labelled alternatives that are generally easier to read
// Note, you can use literals in your rules that match token rules
// and ANTLR will match them up I find this frequently makes the
// grammar easier to read.
ltl
: ltl OR ltl # ltl_or
| ltl AND ltl # ltl_and
| NOT ltl # ltl_not
| '{' ATOM '}' # ltl_atom
;
// Symbols
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
// keywords
OR: 'Or' | 'or';
AND: 'And' | 'and';
NOT: 'Not' | 'not';
// place ATOM *after* keywords to prevent keywords being misidentified as ATOMs
ATOM: ~[{}]+; // Another way of saying "Atom: (~('{' | '}'))+;"
虽然不是真的有必要,但我更喜欢用大写字母命名 Lexer 规则,这样才能真正从解析器规则中脱颖而出(个人品味)
对于 Lexer 规则,有多个 可以 匹配特定字符序列(即歧义)的词法分析器规则是很常见的。完全避免这些将是非常痛苦的,因此 ANTLR 允许它们并使用以下两个规则解决歧义:
- 如果有多个 Lexer 规则匹配输入,则使用匹配最长字符序列的规则。
- 如果多个规则匹配相同长度的字符序列,则使用语法中最先出现的 Lexer 规则。
我是解析和 ANTLR 的新手,如果这是一个愚蠢的问题,请提前致歉。我正在尝试使用 ANTLR 来解析逻辑公式(涉及 AND、OR、NOT)。我有以下语法
grammar LTL;
ltl: ltl_or | ltl_and | ltl_not | Atom;
ltl_and: OPEN_CURLY ltl CLOSE_CURLY And OPEN_CURLY ltl CLOSE_CURLY;
ltl_or: OPEN_CURLY ltl CLOSE_CURLY Or OPEN_CURLY ltl CLOSE_CURLY;
ltl_not: Not OPEN_CURLY ltl CLOSE_CURLY;
Or: 'Or' | 'or';
Atom: (~('{' | '}'))+;
And: 'And' | 'and';
Not: 'Not' | 'not';
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
我的测试用例是 {ABCD()}Or{AB CD()}
,我希望它应该被解析为具有两个原子的有效 Or
公式。上面的语法确实会发生这种情况。但是,如果我交换 Or
规则和 Atom
规则的位置,如下所示:
Atom: (~('{' | '}'))+;
Or: 'Or' | 'or';
我收到错误
line 1:8 no viable alternative at input '{ABCD()}Or'
有人可以指点一下吗?
这是您的语法的重构版本,可以正确处理您提供的输入,并利用其他 ANTLR 习语(希望)使其更易于阅读和维护。 (附有说明进行了哪些更改的注释。)
grammar LTL
;
// *almost* always a good idea to have a start rule that
// consumes everything up to EOF to prevent
// premature termination of parsing input
ltl_start: ltl EOF;
// *IF* you really want to allow a "naked" ATOM
// ltl_start: (ltl | ATOM) EOF;
// since it seems ltls are always wrapped in curlies,
// I've refactored them a bit to simplify also
// used labelled alternatives that are generally easier to read
// Note, you can use literals in your rules that match token rules
// and ANTLR will match them up I find this frequently makes the
// grammar easier to read.
ltl
: ltl OR ltl # ltl_or
| ltl AND ltl # ltl_and
| NOT ltl # ltl_not
| '{' ATOM '}' # ltl_atom
;
// Symbols
OPEN_CURLY: '{';
CLOSE_CURLY: '}';
// keywords
OR: 'Or' | 'or';
AND: 'And' | 'and';
NOT: 'Not' | 'not';
// place ATOM *after* keywords to prevent keywords being misidentified as ATOMs
ATOM: ~[{}]+; // Another way of saying "Atom: (~('{' | '}'))+;"
虽然不是真的有必要,但我更喜欢用大写字母命名 Lexer 规则,这样才能真正从解析器规则中脱颖而出(个人品味)
对于 Lexer 规则,有多个 可以 匹配特定字符序列(即歧义)的词法分析器规则是很常见的。完全避免这些将是非常痛苦的,因此 ANTLR 允许它们并使用以下两个规则解决歧义:
- 如果有多个 Lexer 规则匹配输入,则使用匹配最长字符序列的规则。
- 如果多个规则匹配相同长度的字符序列,则使用语法中最先出现的 Lexer 规则。