0% found this document useful (0 votes)
54 views5 pages

Eliminating Ambiguity in Grammars

This document discusses context-free grammars and ambiguity. It provides examples of ambiguous and unambiguous grammars for expressions involving operators like + and *. It explains that ambiguity can arise from operator precedence not being enforced or from identical operators grouping from either the left or right. The document then presents an unambiguous grammar for expressions and proves it only generates one parse tree for each string. It also discusses how leftmost derivations can be used to show ambiguity and defines inherent ambiguity in languages.

Uploaded by

Sofywka Sofa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views5 pages

Eliminating Ambiguity in Grammars

This document discusses context-free grammars and ambiguity. It provides examples of ambiguous and unambiguous grammars for expressions involving operators like + and *. It explains that ambiguity can arise from operator precedence not being enforced or from identical operators grouping from either the left or right. The document then presents an unambiguous grammar for expressions and proves it only generates one parse tree for each string. It also discusses how leftmost derivations can be used to show ambiguity and defines inherent ambiguity in languages.

Uploaded by

Sofywka Sofa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

MA513: Formal Languages and Automata Theory

Topic: Context-free Grammars (CFG)


Lecture Number 19 Date: September 26, 2011

1 Removing Ambiguity From Grammars


Example 1: Consider the following grammar for expressions:

E → I/E + E/E ∗ E/(E)


I → a/b/Ia/Ib/I0/I1

Example 2: Consider the sentential form E + E ∗ E. It has two derivations from


E (see grammar in Example 1):

1. E ⇒ E + E ⇒ E + E ∗ E.

2. E ⇒ E ∗ E ⇒ E + E ∗ E.

E E

E + E E * E

E * E E + E
(b)
(a)

Figure 1: Two parse trees with the same yield E + E ∗ E

Example 2 says that the grammar in example 1 is ambiguous grammar. There are
two causes of ambiguity in grammar in example 1.

1. The precedence of operators is not respected. While Figure 1(a) properly groups
* before + operator, Figure 1(b) is also a valid perse tree and groups the +
ahead of the *. We need to force only the structure of Figure 1(a) to be legal
in an unambiguous grammar.

2. A sequence of identical operators can group either from the left or from the right.
For example, if *’s in Figure 1 were replaced by +’s, we would see two different
parse trees for the string E + E + E. Since addition and multiplication are
associative, it does not matter whether we group from the left or the right,
but to eliminate ambiguity, we must pick one. The conventional approach is
to insist on grouping from the left, so the structure of Figure 1(b) is the only
correct grouping of two + signs.

1
The solution to the problem of enforcing precedence is to introduce several different
variables, each of which represents those expressions that share a level of binding
strength. Specially:

1. A factor is an expression that can not be broken apart by any adjacent oper-
ator, either a * or a +. The only factors in our expression language are:

(a) Identifiers. It is not possible to separate the letters of an identifier by


attaching an operator.
(b) Any parenthesized expression, no matter what appears inside the paren-
theses. It is the purpose of parentheses to prevent what is inside from
becoming the operand of any operator outside the parentheses.

2. A term is an expression that cannot be broken by the + operator. In our


example, where + and * are the only operators, a term is a product of one
or more factors. For instance, the term a ∗ b can be broken if we use left
associativity and place a1∗ to its left. That is, a1 ∗ a ∗ b is grouped (a1 ∗ a) ∗ b,
which breaks apart the a ∗ b. However, placing additive term, such as a1+ to
its left or +a1 to its right cannot break a ∗ b. The proper grouping of a1 + a ∗ b
is a1 + (a ∗ b), and the proper grouping of a ∗ b + a1 is (a*b)+a1.

3. An expression will henceforth refer to any possible expression, including those


that can be broken by either an adjacent * or an adjacent +. Thus, an ex-
pression for our example is a sum of one or more terms.

From the above discussion, we can write an unambiguous expression grammar as


follows:

Table 1: An unambiguous expression grammar

E → T /E + T
T → F/T ∗ F
F → I/(E)
I → a/b/Ia/Ib/I0/I1

Example 3: The grammar in Table 1 allows only one parse tree for the string
a + a ∗ a; it is shown in the Figure 2.
The fact that the grammar in Table 1 is unambiguous may be far from obvious.
Here are the key observations that explain why no string in the language can have
two different parse trees.

• Any string derived from T , a term, must be a sequence of one or more factors,
connected by *’s. A factor is either a single identifier or any parenthesized
expression.

2
E

E + T

T T * F

F F I

I I a

a a

Figure 2: The sole parse tree for a + a ∗ a

• Because of the form of the two rules for T , the only parse tree for a sequence
of factors is the one that breaks f1 ∗ f2 ∗ . . . ∗ fn , for n > 1 into a term
f1 ∗ f2 ∗ . . . ∗ fn−1 and a factor fn . The reason is that F can not derive
expression like fn−1 ∗ fn without introducing parentheses around them. Thus,
it is not possible that when using the production T → T ∗ F , the F derives
anything but the last of the factor. That is, the parse tree for a term can only
look like Figure 3.

T * F

T * F

T * F

Figure 3: The form of all parse trees for a term

• Likewise an expression is a sequence of terms connected by +. When we use


the production E → E + T to derive t1 + t2 + . . . , tn , then T must derive only
tn , and the E in the body derives t1 + t2 + . . . tn−1 . The reason, again, is that
T can not derive the sum of two or more terms without putting parentheses
around them.

3
2 Leftmost Derivations as a Way to Express Am-
biguity
While derivations are not unique, even if the grammar is unambiguous, it turns out
that, in an unambiguous grammar, leftmost derivation will be unique, and rightmost
derivations will be unique. We shall consider leftmost derivations only, and state
the result for rightmost derivations.
As an example, see the two parse trees in Figure 4 that each yield a + a ∗ a (see the
grammar in Example 1). If we construct leftmost derivations from them we get the
following leftmost derivations from trees (a) and (b), respectively.

E E

E + E E * E

I E * E E + E I

a I I I I a

a a a a
(a) (b)
Figure 4: Trees with yield a + a ∗ a, demonstrating the ambiguity of expression
grammar (see Example 1)

a) E ⇒lm E + E ⇒lm I + E ⇒lm a + E ⇒lm a + E ∗ E ⇒lm a + I ∗ E ⇒lm


a + a ∗ E ⇒lm a + a ∗ I ⇒lm a + a ∗ a

b) E ⇒lm E ∗ E ⇒lm E + E ∗ E ⇒lm I + E ∗ E ⇒lm a + E ∗ E ⇒lm a + I ∗ E ⇒lm


a + a ∗ E ⇒lm a + a ∗ I ⇒lm a + a ∗ a

Note that these two leftmost derivations differ. This example does not prove the
theorem, demonstrates how the differences in the trees force different steps to be
taken in the leftmost derivation.
Theorem: For each grammar G = (V, T, R, S) and string w ∈ T ∗ , w has two
distinct parse trees if and only if w has two distinct leftmost derivations from S.
• For proof see Hopcroft, Motwani and Ullman book.

3 Inherent Ambiguity
A context-free language L is said to be inherently ambiguous if all its grammars
are ambiguous. If even one grammar for L is unambiguous, then L is an unambiguous
language. For example, the language of expressions generated by the grammar in
Example 1 is actually unambiguous. Even though that grammar is ambiguous, there

4
is another grammar for the same language that is unambiguous (see the grammar
in Table 1).
We shall not prove that there are inherently ambiguous languages. Rather we shall
discuss one example of a language that can be proved inherently ambiguous, and we
shall explain intuitively why every grammar for the language must be ambiguous.
The language L in question is:

L = {an bn cm dm |n ≥ 1, m ≥ 1} ∪ {an bm cm dn |n ≥ 1, m ≥ 1}
L is a context-free language. The obvious grammar for L is shown in the Table 2.
It uses separate set of rules to generate the two kind of strings in L.

Table 2: A grammar for an inherently ambiguous language

S → AB/C
A → aAb/ab
B → cBd/cd
C → aCd/aDd
D → bDc/bc

This grammar is ambiguous. For example, the string aabbccdd has the two leftmost
derivations:

1. S ⇒lm AB ⇒lm aAbB ⇒lm aabbB ⇒lm aabbcBd ⇒lm aabbccdd.

2. S ⇒lm C ⇒lm aCd ⇒lm aaDdd ⇒lm aabDdd ⇒lm aabbccdd

and the two parse trees shown in Figure 5.

S S

A B C

a b c B d a C d
A

b c d a D d
a
b D c

b c
(a) (b)

Figure 5: Two parse trees for aabbccdd

The proof that all grammars for L must be ambiguous is complex. However the
essence is as follows. We need to argue that all but a finite number of strings whose
counts of the four symbols a, b, c and d, are all equal must be generated in two
different ways: one in which the a’s and b’s are generated to be equal and the c’s
and d’s are generated to be equal, and a second way, where the a’s and d’s are
generated to be equal and likewise the b’s and c’s.

Common questions

Powered by AI

Factors, terms, and expressions have distinct roles in resolving ambiguities within context-free grammars (CFGs) by clearly delineating levels of operator precedence and associativity. Factors are the most atomic units, such as identifiers or parenthesized expressions that cannot be disrupted by operators. Terms consist of factors linked by multiplication operators (*), respecting multiplicative precedence and remaining unbroken by addition. Expressions are higher-level constructs that can include sums of terms and are parsed according to additive precedence. By structuring grammars to separate these elements into hierarchical levels, CFGs can enforce correct precedence rules unambiguously, preventing overlapping interpretations of identical strings .

The classification of a context-free language as inherently ambiguous is significant because it indicates fundamental limitations in expression generation within that language framework. This implies that no matter how the grammar is constructed, at least some strings produced will allow multiple parse trees, presenting challenges in parsing, compiler design, and syntactic analysis. It affects how the language can be implemented and understood, as ambiguity leads to inconsistencies in expression evaluation and interpretation, particularly critical in programming language syntax where precision is necessary .

Constructs like '*' and '+' significantly influence parse tree generation due to their distinct precedence levels, with '*' generally having higher precedence over '+'. In CFGs, failing to adequately distinguish precedence and associativity for these operators can lead to multiple valid parse trees for the same expression, resulting in ambiguous grammar. For example, 'a + a * a' must be parsed as 'a + (a * a)' to ensure correct mathematical semantics. Careful handling ensures that operations are executed according to intended logic—multiplication before addition in this case—thereby maintaining consistency and correctness across expression evaluations .

Ambiguity in programming language grammars poses significant challenges in compiler and interpreter design, as it leads to multiple possible interpretations of program logic, affecting consistency and reliability. Ambiguous grammars can result in different parse trees for the same program code, leading to varying execution outcomes, which is problematic for code maintainability and debugging. Resolving ambiguity ensures that code is interpreted uniformly, enhancing compiler accuracy, easing language standardization, and allowing developers to predict program behavior reliably. This clarity supports robust software development by reducing errors, improving performance optimization, and facilitating more effective tool creation .

In unambiguous grammars, leftmost derivations remain unique because the rules inherently enforce a single, consistent order of operations and parse trees. For any given string, there can be no alternate sequence of derivation steps since each choice of production and expansion leads unambiguously to the same final parse tree. This consistency ensures that, despite multiple possible sequences technically existing during derivation, only one is valid per the grammar's construction, preserving uniqueness for both leftmost and rightmost derivations .

The grammar in Table 1 achieves unambiguity by separating the constructs according to operator precedence. It differentiates between factors, terms, and expressions. Factors (F) cannot be broken by any operator and include identifiers or parenthesized expressions. Terms (T) consist of sequences of one or more factors connected by * and cannot be broken by +. Expressions (E) are sequences of terms separated by +. By structuring the grammar with these distinctions, 'a + a * a' forms only one parse tree with the * operator having higher priority, correctly parsing as 'a + (a * a)' .

Inherent ambiguity in context-free languages refers to the characteristic of a language that cannot have an unambiguous grammar, meaning all grammars defining the language permit multiple parse trees for some strings. Language L = {anbncmdm|n ≥1, m ≥1} ∪ {anbmcmdn|n ≥1, m ≥1} exemplifies this as any grammar that can generate this language allows for multiple valid parse sequences. For instance, the string 'aabbccdd' can be derived in two distinct ways: either equating a's and b's and c's and d's or vice versa (equating a's and d's and b's and c's), leading to inherently different parse arrangements. Thus, despite constructing grammars with strict rules, the structural nature of L's string patterns mandates ambiguity .

Two leftmost derivations for the same string illustrate grammar ambiguity by showing different sequences of production applications leading to identical results. For example, in a grammar with ambiguous rules, the string 'a + a * a' can have one derivation starting with E ⇒lm E + E ⇒lm I + E ⇒lm a + E ∗ E ⇒lm a + I ∗ E ⇒lm a + a ∗ I ⇒lm a + a ∗ a, and another starting with E ⇒lm E ∗ E ⇒lm E + E ∗ E ⇒lm a + E ∗ E ⇒lm a + a ∗ E ⇒lm a + a ∗ a . Despite reaching the same result, the differing production paths demonstrate that the grammar allows multiple valid parse trees for the expression, thereby highlighting its ambiguity.

Operator associativity affects the generation of parse trees by determining the order in which operators of the same precedence are grouped during parsing. In ambiguous grammars, expressions such as E + E + E can be parsed in different ways depending on whether the operators associate to the left or the right. To resolve such ambiguities, a common convention is to choose left associativity, which dictates that operations are grouped from the left. For example, E + E + E is parsed as (E + E) + E. This consistent left-heavy grouping simplifies parsing logic and eliminates potential ambiguity in parse tree formations .

The ambiguity in Example 1's grammar for expressions arises due to the lack of operator precedence and associativity. This is evident in the possible derivation of expressions like E + E ∗ E, which have two distinct parse trees: one grouping * before +, and another grouping + before *. Additionally, sequences of identical operators can group from the left or right, further contributing to ambiguity. To resolve this, the grammar can be modified to enforce operator precedence, introducing different variables for expressions of varying binding strengths: factors, terms, and expressions. This ensures that * is evaluated before +, and expressions are grouped left-associatively, eliminating ambiguity .

You might also like