A parsing is a process, which takes the input string w and
produces either a parse tree(syntactic structure) or generate syntactic errors
The parser takes the tokens as input, and generates a tree
like structure called parse tree
Grammar naturally describes the hierarchical syntactical
structure of the sentences of the language they define
These hierarchical structures are called parse trees
A parse tree has
Terminals
at the leaves
Non-Terminals
at the interior nodes
Sub
tree of a parse tree describes an instance of an abstraction of the sentence
Example 1:
Example 2:
E → E + E | E * E | (E) | id
Statement A * B + C
Ambiguity
A Grammar is said to be ambiguous if it produces more than
one parse tree for some sentence
Ambiguous Grammars
should be avoided
Example:
The below grammar is ambiguous because there are two
distinct parse trees for the statement
A = B + C * A
A = B + C * A
Example 2:
Let G be a Context Free Grammar for which the production rules are given as below
Let G be a Context Free Grammar for which the production rules are given as below
S → aB | bA
A → a | aS | bAA
B → b | bS | aBB
Derive the string ‘aaabbabbba’ using grammar
This grammar is ambiguous because it allows the expression
to grow on the both sides (left and right), rather than allowing the parse tree
of an expression to grow only on the right
Syntactic ambiguity is a problem because compilers often
base the semantics of structures on their syntactic form
- If a language structure has more than one parse tree, then its meaning cannot be determined uniquely
The other characteristics to determine the ambiguity of the
grammar are
- If the grammar generates more than one leftmost derivation
- If the grammar generates more than one rightmost derivation
A general way to avoid the ambiguity is rewriting the
grammar
Instead of rewriting the grammar to solve ambiguity
- Use more natural grammar along with disambiguating declarations with enforcing operator precedence and associativity
Example:
Find whether the following grammar is ambiguous or not.
S → AB | aaB
A → a | Aa
B → b
Construct parse tree for the string ‘aab’.
There are two different parse trees for deriving string 'aab'. Hence the above given grammar is an ambiguous grammar
Operator Precedence
The order of evaluation is the basic semantic issue when an
expression contains more than one operator
Example: A + B + C * A
In this
expression it is add, then multiply or vice versa
This statement issue is addressed by Operator Precedence
A parse tree can support operator precedence by the rule
that the Operator Precedence lower in parse trees are evaluated before those
generated higher up in the parse tree
This
rule may allow the expression to grow on the both sides (left and right)
This
can be avoided by enforcing the Operator Precedence
Example 1:
Example 2:
Derivation : A + B + C * A <assign> => <id> = <expr>
Derivation : A + B + C * A <assign> => <id> = <expr>
- Every derivation with an unambiguous grammar has a unique parse tree
- Both of the above derivations are represented by the same parse tree
Associativity of Operators
Associativity is the order of evaluation of operators with the same precedence
When an expression includes two operators that have the same precedence (as * and /), for example A / B * C a semantic rule is required to specify which should have precedence. This rule is named associativity
Consider the following example of an assignment statement of a language which supports power operator (**)
Example: A = 3** 3 ** 4
This execution can be evaluated to A=531441 with left associativity and can be evaluated to A = A will be 262144
To fix this ambiguity, a grammar can define associativity rules to make it left recursive or right recursive
Associativity is the order of evaluation of operators with the same precedence
When an expression includes two operators that have the same precedence (as * and /), for example A / B * C a semantic rule is required to specify which should have precedence. This rule is named associativity
Consider the following example of an assignment statement of a language which supports power operator (**)
Example: A = 3** 3 ** 4
This execution can be evaluated to A=531441 with left associativity and can be evaluated to A = A will be 262144
To fix this ambiguity, a grammar can define associativity rules to make it left recursive or right recursive
Left Recursive: A grammar rule that has it its LHS also
appearing at the beginning of its RHS
<expr>
→ <expr> + <term>
Supports
left associativity
Right Recursive: A grammar rule that has its LHS at the
rught end of the RHS
Example:
<factor>
→ <expr> ** <factor>
|<expr>
<expr>
→ (<expr>)
|id
This can be used to describe exponentiation right
associative operator.
Home
|