Search code examples
f#fsyacc

Extending example grammar for Fsyacc with unary minus


I tried to extend the example grammar that comes as part of the "F# Parsed Language Starter" to support unary minus (for expressions like 2 * -5).

I hit a block like Samsdram here

Basically, I extended the header of the .fsy file to include precedence like so:

......
%nonassoc UMINUS
....

and then the rules of the grammar like so:

...
Expr: 
| MINUS Expr %prec UMINUS   { Negative ($2) }
...

also, the definition of the AST:

...
and Expr =
    | Negative of Expr
.....

but still get a parser error when trying to parse the expression mentioned above.

Any ideas what's missing? I read the source code of the F# compiler and it is not clear how they solve this, seems quite similar

EDIT

The precedences are ordered this way:

%left ASSIGN
%left AND OR
%left EQ NOTEQ LT LTE GTE GT
%left PLUS MINUS
%left ASTER SLASH
%nonassoc UMINUS

Solution

  • Had a play around and managed to get the precedence working without the need for %prec. Modified the starter a little though (more meaningful names)

    Prog:
        | Expression EOF { $1 }
    
    Expression:
        | Additive { $1 }
    
    Additive:
        | Multiplicative { $1 }
        | Additive PLUS  Multiplicative { Plus($1, $3)  }
        | Additive MINUS Multiplicative { Minus($1, $3) }
    
    Multiplicative:
        | Unary { $1 }
        | Multiplicative ASTER Unary { Times($1, $3)  }
        | Multiplicative SLASH Unary { Divide($1, $3) }
    
    Unary:
        | Value { $1 }
        | MINUS Value { Negative($2) }
    
    Value:
        | FLOAT { Value(Float($1)) }
        | INT32 { Value(Integer($1)) }
        | LPAREN Expression RPAREN { $2 }
    

    I also grouped the expressions into a single variant, as I didn't like the way the starter done it. (was awkward to walk through it).

    type Value =
        | Float   of Double
        | Integer of Int32
        | Expression of Expression
    
    and Expression =
        | Value of Value
        | Negative of Expression
        | Times  of Expression * Expression
        | Divide of Expression * Expression
        | Plus  of Expression * Expression
        | Minus of Expression * Expression
    
    and Equation =
        | Equation of Expression