Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression parser grammar and left-associativity

I have been trying create my parser for expression with variables and simplify them to quadratic expression form.

This is my parser grammar:

Exercise : Expr '=' Expr
Expr : Term [+-] Expr | Term
Term : Factor [*/] Term | Factor
Factor: Atom [^] Factor | Atom
Atom: Number | Identified | [- sqrt] Atom | '(' Expr ')'

For parsing I'm using recursive descent parser. Let's say I'd like to parse this:

" 2 - 1 + 1 = 0"

and the result is 0, parser creates wrong tree:

  -
 / \
2   +
   / \
  1   1

How can I make this grammar left-associative? I'm newbie at this, please can you advice me source where I can find more information? Can I achieve this with recursive descent parser?

like image 857
Martin Bodocky Avatar asked Dec 01 '13 23:12

Martin Bodocky


People also ask

What is left-associative grammar?

Left-associative operators of the same precedence are evaluated in order from left to right. For example, addition and subtraction have the same precedence and they are left-associative. In the expression 10-4+2, the subtraction is done first because it is to the left of the addition, producing a value of 8.

How do you know if a grammar is left-associative?

For example, a+b+c can be interpreted as ((a + b) + c) or as (a + (b + c)). We say that + is left-associative if operands are grouped left to right as in ((a + b) + c). We say it is right-associative if it groups operands in the opposite direction, as in (a + (b + c)).

How do you measure associativity in grammar?

For the given unambiguous grammar, The associativity of operators is decided by checking the Type Of Recursion in the production. If the production has left recursion, then the operator is left associative. If the production has right recursion, then the operator is right associative.

What are left-associative and right associative operators?

Operators may be associative (meaning the operations can be grouped arbitrarily), left-associative (meaning the operations are grouped from the left), right-associative (meaning the operations are grouped from the right) or non-associative (meaning operations cannot be chained, often because the output type is ...


1 Answers

Take a look at Parsing Expressions by Recursive Descent by Theodore Norvell

There he gives three ways to solve the problem.
1. The shunting yard algorithm.
2. Classic solution by factoring the grammar.
3. Precedence climbing

Your problem stems from the fact that your grammar needs several changes, one example being

Exrp: Term { [+-] Expr} | Term

notice the addition of the { } around [+-] Expr indicating that they should be parsed together and that there can 0 or more of them.

Also by default you are building the tree as

  -
 / \
2   +
   / \
  1   1

i.e. -(2,+(1,1))

when you should be building the tree for left associative operators of the same precedence as

     +
    / \
   -   1
  / \
 2   1

i.e. +(-(2,1),1)

Since there are three ways to do this in the paper I won't expand on them here. Also you mention that you are new to this so you should get a good compiler book to understand the details of you will encounter reading the paper. Most of these methods are implemented in common programming languages and available free on the internet, but be aware that many people do what you do and post wrong results.

The best way to check if you have it right is with a test like this using a multiple sequence of subtraction operations:

7-3-2 = 2

if you get

7-3-2 = 6 or something else

then it is wrong.

like image 104
Guy Coder Avatar answered Sep 19 '22 11:09

Guy Coder