我目前正在为自己的语言构建解析器,但是我在使用优先级时遇到了麻烦(我认为这就是问题所在)。我仅在构建AST时才发现此问题。我定义了以下标记:
%token T_SEMICOLON T_COMMA T_PERIOD T_RETURN T_BOOLEAN T_EXTENDS T_TRUE T_FALSE T_IF T_DO T_NEW T_ELSE T_EQUALSSIGN T_PRINT T_INTEGER T_NONE T_WHILE T_NUMBER T_VARIABLE T_LEFTCURLY T_RIGHTCURLY T_LEFTPAREN T_RIGHTPAREN T_ARROW T_EOF
%left T_OR
%left T_AND
%left T_MINUS T_EQUALSWORD T_PLUS
%left T_GE T_GEQ
%left T_MULTIPLY T_DIVIDE
%right T_NOT
(在这种情况下,只有优先级才重要),我有一个采用以下形式的语法
Something: T_PRINT expression T_SEMICOLON
我有几个表达作品,其中一些是
expression : expression T_PLUS expression {$$ = new PlusNode($1, $3);}
| expression T_MINUS expression {$$ = new MinusNode($1, $3);}
| expression T_EQUALSWORD expression {$$ = new EqualNode($1, $3);}
| expression T_MULTIPLY expression {$$ = new TimesNode($1, $3);}
| expression T_DIVIDE expression {$$ = new DivideNode($1, $3);}
| T_NOT expression {$$ = new NotNode($2);}
| T_MINUS expression {$$ = new NegationNode($2);}
| T_VARIABLE {$$ = new VariableNode($1);}
| T_NUMBER {$$ = new IntegerLiteralNode($1);}
| T_TRUE {$$ = new BooleanLiteralNode(new IntegerNode(1));}
| T_FALSE {$$ = new BooleanLiteralNode(new IntegerNode(0));}
| T_NEW T_VARIABLE {$$ = new NewNode($2, NULL);}
当我尝试解析类似print true equals new c0 - new c0;
的内容时,我得到了一个奇怪的输出AST,看起来像Print(Minus(Equal(BooleanLiteral(1), New("c0")), New("c0")))
。即使我另行定义,这里看起来T_EQUALSWORD令牌的优先级也比T_MINUS令牌高?
如果我将减号更改为加号,也会发生此问题;输入print true equals new c0 + new c0;
得到Print(Equal(BooleanLiteral(1), GreaterEqual(New("c0"), New("c0"))))
作为输出。表单似乎正确,但由于某种原因我正在获取T_GEQ令牌而不是T_PLUS?
有趣的是,它可以正确解析T_MULTIPLY和T_DIVIDE:
输入:print true equals new c0 * new c0;
输出:Print(Equal(BooleanLiteral(1), Times(New("c0"), New("c0"))))
输入:print true equals new c0 / new c0;
输出:Print(Equal(BooleanLiteral(1), Divide(New("c0"), New("c0"))))
因此,这似乎可以与乘法和除法一起正常使用,但不能通过加号和减号来解决。有什么想法吗?
编辑:我在T_EQUALSWORD生产中添加了%prec T_OR
,这在我使用减法时解决了这个问题,但是当我使用加法时,我仍然得到了奇怪的T_GEQ令牌。
答案 0 :(得分:3)
此行
%left T_MINUS T_EQUALSWORD T_PLUS
表示这三个运算符具有相同的优先级,并且从左到右关联。您得到的第一个结果与此一致。
a - b - c (a - b) - c # Left associative
a - b = c (a - b) = c # Also left associative
a = b - c (a = b) - c # Once again
如果您希望等式的优先级较低,请为其指定优先级。
第二个问题是生成了错误的令牌,可能是因为您的扫描仪生成了错误的令牌。