Grammar expressions with operators

743 views Asked by At

I'm struggling making a parser that recognize operations. The operators can be binary arithmetic: (+, -, *, /), binary relationship: (==, <>) or unary (++, --).

The arithmedtic operators should have right associativity, relationship operators aren't associative. The priority of the operators is: first multiplicative (*, /), second additive (+, -) and last relationship (==, <>). If there is any unary operator it should be after an <Id>.

In the expressions can be parenthesis and they have maximum priority.

Examples: ab--, cd++, ef(a-- * b++), ij(aa++ + b), c <> a * b, d++ * 3, c == true, l++ + m(a, a)

Bad cases: 3++, 3.1++, (a)++, a()++, true++

This is the code I have with RelationOp(), but it doesn't recognize additions. Changeing RelationOp() with AdtOp() in Expression method recognizes additions, but I can't figure what I need to change to make it work relation operators work.

void Expression() : {}
    {
        ["-"] Term() [RelationOp() OtherTerms()]
    }

void Term() : {}
    {
        Factor() [MultiOp() Term()]
    }

void OtherTerms() : {}
    {
        Term() [AdtOp() OtherTerms()]
    }

void Factor() : {}
    {
        <Id> [("++" | "--")]
        | <ConstFloat>
        | <ConstInt>
        | "(" Expression() ")"
        | "true"
        | "false"
    }

void AdtOp() : {}
    {
        "+"
        | "-"
    }

void MultiOp() : {}
    {
        "*"
        | "/"
    }

void RelationOp() : {}
    {
        "=="
        | "<>"
    }

Thanks.

1

There are 1 answers

1
Theodore Norvell On BEST ANSWER

Almost there. Change Expression to

void Expression() : {}
    {
        OtherTerms() [RelationOp() OtherTerms()]
    }

I'm not sure what the ["-"] was doing there, since your description of the grammar doesn't mention unary -. So the rest is based on speculation about what the language might be and how the precedence goes.

If you want unary minus to have highest priority apart from ++ and -- --as in C-- change Factor to

void Factor() : {}
    {
          "-" Factor()
        | <Id> [("++" | "--")]
        | ...etc...
    }

If you prefer that unary minus has priority lower than * and /, you could change Factor to

void Factor() : {}
    {
          "-" Term()
        | <Id> [("++" | "--")]
        | ...etc...
    }

This makes your grammar ambiguous --for example -a*b has two parses-- and so JavaCC will issue a warning, but you can safely ignore this warning; only the correct parse will be made.