Antlr4 语法 - 识别语法的麻烦
Antlr4 grammar - trouble identifying grammar
我正在使用 Antlr4 来解析类似布尔值的 DSL。
这是我的语法:
grammar filter;
filter: overall EOF;
overall
: LPAREN overall RPAREN
| category
;
category
: expression # InferenceCategory
| category AND category # CategoryAndBlock
| label COLON expression # CategoryBlock
| LPAREN category RPAREN # NestedCategory
;
expression
: NOT expression # NotExpr
| expression AND expression # AndExpr
| expression OR expression # OrExpr
| atom # AtomExpr
| LPAREN expression RPAREN # NestedExpression
;
label
: ALPHANUM
;
atom
: ALPHANUM
;
这是要解析的示例输入字符串:
(cat1:(1 OR 2) AND cat2:( 4 ))
此语法适用于此输入;它生成以下完全适合我需要的解析树:
但是,DSL 有一个奇怪的情况,当没有指定其他类别时,"cat1" 标签是隐式的。这是 InferenceCategory 标记捕获的内容,稍后将在我的代码中将此表达式作为类别处理。
例如,
((1 OR 2) AND cat2:( 4 ))
我得到(如预期):
但是,在下面的例子中:
cat2:( 4 ) AND (1 OR 2)
我得到:
请注意,第二个块未被标识为 InferenceCategory,而是第一个类别下的普通表达式。这是因为那里的语法将 cat2: 之后的 (4) 解析为普通表达式,而之后的所有内容都被解析为普通表达式。
有什么办法可以解决这个问题吗?我试过:
label COLON expression (AND category)* # CategoryBlock
(这不起作用)
和
category AND category AND category
("works",但它非常笨拙,只适用于我正好有三个类别的特定情况。再多了,它又坏了。)
像 NOT expression # NotExpr
这样的 "alternative labels" 不会对您的解析树产生影响。它们是纯语义的。它们将导致代码生成过程创建特定的签名,您可以在访问者或侦听器中覆盖这些签名。
这背后的基本原理是,例如,您将获得多个替代标签,而不是只获得一个 expression
的访问者覆盖。这样,您就不必在对它采取行动之前检查 expression
并确定它是什么类型。相反,例如,您将获得 # OrExpr
的覆盖,一旦进入该覆盖代码,您就会知道您正在处理 OR,在 OR 标记的每一侧都有一个表达式。
解析树很有用,但很多语义只有在编写监听器或访问器代码时才会变得明显。
我正在使用 Antlr4 来解析类似布尔值的 DSL。
这是我的语法:
grammar filter;
filter: overall EOF;
overall
: LPAREN overall RPAREN
| category
;
category
: expression # InferenceCategory
| category AND category # CategoryAndBlock
| label COLON expression # CategoryBlock
| LPAREN category RPAREN # NestedCategory
;
expression
: NOT expression # NotExpr
| expression AND expression # AndExpr
| expression OR expression # OrExpr
| atom # AtomExpr
| LPAREN expression RPAREN # NestedExpression
;
label
: ALPHANUM
;
atom
: ALPHANUM
;
这是要解析的示例输入字符串:
(cat1:(1 OR 2) AND cat2:( 4 ))
此语法适用于此输入;它生成以下完全适合我需要的解析树:
但是,DSL 有一个奇怪的情况,当没有指定其他类别时,"cat1" 标签是隐式的。这是 InferenceCategory 标记捕获的内容,稍后将在我的代码中将此表达式作为类别处理。
例如,
((1 OR 2) AND cat2:( 4 ))
我得到(如预期):
但是,在下面的例子中:
cat2:( 4 ) AND (1 OR 2)
我得到:
请注意,第二个块未被标识为 InferenceCategory,而是第一个类别下的普通表达式。这是因为那里的语法将 cat2: 之后的 (4) 解析为普通表达式,而之后的所有内容都被解析为普通表达式。
有什么办法可以解决这个问题吗?我试过:
label COLON expression (AND category)* # CategoryBlock
(这不起作用)
和
category AND category AND category
("works",但它非常笨拙,只适用于我正好有三个类别的特定情况。再多了,它又坏了。)
像 NOT expression # NotExpr
这样的 "alternative labels" 不会对您的解析树产生影响。它们是纯语义的。它们将导致代码生成过程创建特定的签名,您可以在访问者或侦听器中覆盖这些签名。
这背后的基本原理是,例如,您将获得多个替代标签,而不是只获得一个 expression
的访问者覆盖。这样,您就不必在对它采取行动之前检查 expression
并确定它是什么类型。相反,例如,您将获得 # OrExpr
的覆盖,一旦进入该覆盖代码,您就会知道您正在处理 OR,在 OR 标记的每一侧都有一个表达式。
解析树很有用,但很多语义只有在编写监听器或访问器代码时才会变得明显。