简体   繁体   English

LL1语法用于算术表达式和赋值

[英]LL1 grammar for arithmetic expressions and assignments

I would like to design an LL1 grammar for arithmetic equations and variable assignments. 我想为算术方程式和变量赋值设计一个LL1语法。 I began with this grammar: 我从这种语法开始:

I have a nonambiguous grammar for arithmetic expressions: 我对算术表达式有一个明确的语法:

E → T E’
E’ →  | + E
T → id T’
T’ →  | * T

However, I'm not sure how to incorporate variable assignments into the E productions. 但是,我不确定如何将变量分配合并到E生产中。

How I tried previously was: 我以前的尝试是:

    stmt -> assignment SEMI | RETURN stmt_prime 
   | LBRACE stmt_list RBRACE 
   | IF LPAREN assignment RPAREN stmt stmt_prime_prime 
   | FOR LPAREN assignment SEMI assignment SEMI assignment RPAREN stmt | 
    stmt_prime -> SEMI | -> assignment SEMI
    stmt_prime_prime -> NOELSE 
    | ELSE stmt
    assignment -> ID typ ASSIGN expr | expr  
    expr -> TE* 
    E* -> + TE* | -TE* | epsilon
    T -> FT*
    T* -> * FT* | / FT* | epsilon
    F -> (E) | int_literal | TRUE | FALSE
assignment -> ID ASSIGN expr | expr

(I'm ignoring the typ part because I assume it got there by accident) (我忽略了typ部分,因为我认为它是偶然到达的)

The problem here is that both ID ASSIGN expr and expr could start with an ID (or at least they could if T contained ID as an option, which I assume was the intention), so this isn't LL(1). 这里的问题是ID ASSIGN exprexpr都可以以ID开头(或者,如果T包含ID作为选项(我认为是故意的话),则至少可以这样),所以这不是LL(1)。 It is LL(2) though, so if you're fine with that, you can just add an andalso next_token = ASSIGN to the if condition in your parser and be done with it. 不过它是LL(2),因此,如果您对此感到满意,则可以在解析器的if条件中添加andalso next_token = ASSIGN并完成此操作。

If you do need it to be LL(1), you'll have to adjust the language allowed by your parser, I'm afraid (that is, there is no LL(1) grammar that matches exactly the same language as your current grammar). 如果确实需要将其设为LL(1),恐怕必须调整解析器允许的语言(也就是说,没有与您当前语言完全相同的LL(1)语法)语法)。 One easy way out would be to simply add a keyword like SET before assignment, though admittedly that's ugly. 一种简单的解决方法是在分配之前简单地添加一个像SET这样的关键字,尽管公认这很丑陋。

The other alternative would be to allow arbitrary expressions as the left operand of = , making your assignment rule: 另一种选择是允许任意表达式作为=的左操作数,从而使您的赋值规则为:

assignment -> exp (ASSIGN exp)?

Which is LL(1). 这是LL(1)。 The downside of this is that it allows a lot of non-sensical code such as 1+2 := 42 , but you can fix that outside of the grammar. 这样做的缺点是,它允许使用许多无意义的代码,例如1+2 := 42 ,但是您可以在语法之外进行修复。 That is, your code for parsing assignments can simply call parse_exp and then, if the next token is an ASSIGN and the expression returned by parse_exp is not just an identifier, raise an error that the left-side of an assignment must be an identifier. 也就是说,您用于解析分配的代码可以简单地调用parse_exp ,然后,如果下一个标记是ASSIGN并且parse_exp返回的表达式不仅仅是一个标识符,则会产生一个错误,指出分配的左侧必须是一个标识符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM