二元运算符的解释变体
Interpretation variants of binary operators
我正在为一种包含一些二元运算符的语言编写语法,这些运算符也可以用作一元运算符(运算符右侧的参数)并且为了更好的错误恢复我希望它们是也可用作 nular 运算符)。
我的简化语法如下所示:
开始:
代码EOF
;
code:
(binaryExpression SEMICOLON?)*
;
binaryExpression:
binaryExpression BINARY_OPERATOR binaryExpression //TODO: check before primaryExpression
| primaryExpression
;
primaryExpression:
unaryExpression
| nularExpression
;
unaryExpression:
operator primaryExpression
| BINARY_OPERATOR primaryExpression
;
nularExpression:
operator
| BINARY_OPERATOR
| NUMBER
| STRING
;
operator:
ID
;
BINARY_OPERATOR
只是一组输入解析器的已定义关键字。
我的问题是 Antlr 更喜欢将 BINARY_OPERATOR
s 用作一元表达式(如果没有其他选择,则使用 nualr 表达式)而不是尝试在二进制表达式中使用它们,因为我需要这样做。
例如,考虑以下输入:for varDec from one to twelve do something
其中 from
、to
和 do
是二元运算符,解析器的输出如下:
如您所见,它将所有二元运算符解释为一元运算符。
我要实现的目标如下:尝试匹配二进制表达式中的每个 BINARY_OPERATOR
并且 仅当不可能时 尝试匹配它们作为一元表达式,如果这也不可能,那么它可能被认为是一个 nular 表达式(只有 BINARY_OPERATOR
是表达式的唯一内容时才会出现这种情况)。
有没有人知道如何实现所需的行为?
您允许运算符像操作数 ("nularExpression") 和操作数像运算符 ("operator: ID")。在这两个奇怪的决定之间,您的语法是 100% 不明确的,并且永远不需要解析二元运算符。我对 Antlr 了解不多,但令我惊讶的是它没有警告你你的语法完全有歧义。
Antlr 有 handle and recover from errors 的机制。使用它们比编写故意模棱两可的语法要好得多,这种语法会使错误的结构成为可接受的语法的一部分。 (正如我所说,我不是 Antlr 专家,但有一些 Antlr 专家经常路过这里;如果你问 specific 关于错误恢复的问题,我相信你会得到一个很好的答案。您可能还想搜索此站点以获取有关 Antlr 错误恢复的问题和答案。)
相当标准的方法是使用单个递归规则来建立可接受的表达式语法。 ANTLR 默认是左结合的,所以 op expr
满足 "argument to the right side of the operator" 规定的一元运算要求。有关关联性的进一步讨论,请参阅 TDAR 第 70 页。
Ex1: -y+x
-> binaryOp{unaryOp{-, literal}, +, literal}
例 2:-y+-x
-> binaryOp{unaryOp{-, literal}, +, unaryOp{-, literal}}
expr
: LPAREN expr RPAREN
| expr op expr #binaryOp
//| op expr #unaryOp // standard formulation
| op literal #unaryOp // limited formulation
| op #errorOp
| literal
;
op : .... ;
literal
: KEYWORD
| ID
| NUMBER
| STRING
;
我想我现在要写的是@GRosenberg 的回答的意思。然而,由于我花了一段时间才完全理解它,我会为我的问题提供一个具体的解决方案,以防其他人遇到这个问题并正在搜索或回答:
诀窍是删除在 unaryExpression
规则中使用 BINARY_OPERATOR
的选项,因为这总是首选。相反,我真正想要的是指定如果没有左侧参数,那么以一元方式使用 BINARY_OPERATOR
应该没问题。这就是我必须指定的方式:
binaryExpression:
binaryExpression BINARY_OPERATOR binaryExpression
| BINARY_OPERATOR primaryExpression
| primaryExpression
;
只有在 BINARY_OPERATOR
左侧没有任何内容的情况下,这种语法才有可能出现,而在其他情况下,必须使用二进制语法。
我正在为一种包含一些二元运算符的语言编写语法,这些运算符也可以用作一元运算符(运算符右侧的参数)并且为了更好的错误恢复我希望它们是也可用作 nular 运算符)。
我的简化语法如下所示:
开始:
代码EOF
;
code:
(binaryExpression SEMICOLON?)*
;
binaryExpression:
binaryExpression BINARY_OPERATOR binaryExpression //TODO: check before primaryExpression
| primaryExpression
;
primaryExpression:
unaryExpression
| nularExpression
;
unaryExpression:
operator primaryExpression
| BINARY_OPERATOR primaryExpression
;
nularExpression:
operator
| BINARY_OPERATOR
| NUMBER
| STRING
;
operator:
ID
;
BINARY_OPERATOR
只是一组输入解析器的已定义关键字。
我的问题是 Antlr 更喜欢将 BINARY_OPERATOR
s 用作一元表达式(如果没有其他选择,则使用 nualr 表达式)而不是尝试在二进制表达式中使用它们,因为我需要这样做。
例如,考虑以下输入:for varDec from one to twelve do something
其中 from
、to
和 do
是二元运算符,解析器的输出如下:
如您所见,它将所有二元运算符解释为一元运算符。
我要实现的目标如下:尝试匹配二进制表达式中的每个 BINARY_OPERATOR
并且 仅当不可能时 尝试匹配它们作为一元表达式,如果这也不可能,那么它可能被认为是一个 nular 表达式(只有 BINARY_OPERATOR
是表达式的唯一内容时才会出现这种情况)。
有没有人知道如何实现所需的行为?
您允许运算符像操作数 ("nularExpression") 和操作数像运算符 ("operator: ID")。在这两个奇怪的决定之间,您的语法是 100% 不明确的,并且永远不需要解析二元运算符。我对 Antlr 了解不多,但令我惊讶的是它没有警告你你的语法完全有歧义。
Antlr 有 handle and recover from errors 的机制。使用它们比编写故意模棱两可的语法要好得多,这种语法会使错误的结构成为可接受的语法的一部分。 (正如我所说,我不是 Antlr 专家,但有一些 Antlr 专家经常路过这里;如果你问 specific 关于错误恢复的问题,我相信你会得到一个很好的答案。您可能还想搜索此站点以获取有关 Antlr 错误恢复的问题和答案。)
相当标准的方法是使用单个递归规则来建立可接受的表达式语法。 ANTLR 默认是左结合的,所以 op expr
满足 "argument to the right side of the operator" 规定的一元运算要求。有关关联性的进一步讨论,请参阅 TDAR 第 70 页。
Ex1: -y+x
-> binaryOp{unaryOp{-, literal}, +, literal}
例 2:-y+-x
-> binaryOp{unaryOp{-, literal}, +, unaryOp{-, literal}}
expr
: LPAREN expr RPAREN
| expr op expr #binaryOp
//| op expr #unaryOp // standard formulation
| op literal #unaryOp // limited formulation
| op #errorOp
| literal
;
op : .... ;
literal
: KEYWORD
| ID
| NUMBER
| STRING
;
我想我现在要写的是@GRosenberg 的回答的意思。然而,由于我花了一段时间才完全理解它,我会为我的问题提供一个具体的解决方案,以防其他人遇到这个问题并正在搜索或回答:
诀窍是删除在 unaryExpression
规则中使用 BINARY_OPERATOR
的选项,因为这总是首选。相反,我真正想要的是指定如果没有左侧参数,那么以一元方式使用 BINARY_OPERATOR
应该没问题。这就是我必须指定的方式:
binaryExpression:
binaryExpression BINARY_OPERATOR binaryExpression
| BINARY_OPERATOR primaryExpression
| primaryExpression
;
只有在 BINARY_OPERATOR
左侧没有任何内容的情况下,这种语法才有可能出现,而在其他情况下,必须使用二进制语法。