simplifying cfgs there are several ways in which context-free grammars can be simplified. one...

35
Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols those that cannot be part of a derivation (or parse tree) Symbols may be useless in one of two ways. they may not be reachable from the start symbol. or they may be variables that cannot derive a string of terminals

Upload: ambrose-hopkins

Post on 16-Dec-2015

226 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Simplifying CFGs

There are several ways in which context-free grammars can be simplified.

One natural way is to eliminate useless symbols– those that cannot be part of a derivation (or parse tree)

Symbols may be useless in one of two ways. – they may not be reachable from the start symbol.– or they may be variables that cannot derive a string of

terminals

Page 2: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Example of a useless symbol

Consider the CFG G with rules– S → aBC, B → b|Cb, C → c|cC, D → d

Here the symbols S, B, C, a, b, and c are reachable, but D is not.

D may be removed without changing L(G)

Page 3: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Reachable symbols

In a CFG, a symbol is reachable iff it is S or– it appears in , where A → is a rule of the grammar, and A

is reachable

So in the grammar above– we first find that S is reachable– then that a, B, and C are– and finally that b and c are.

A symbol that is unreachable cannot be part of a derivation. It may be eliminated along with all of its rules.

Page 4: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Another reachability example

Suppose the grammar G instead had rules– S → aB, B → b|Cb, C → c|cC, D → d,

Then we would first see that S is reachable– then that a and B are– then that b and C are– and finally that c is

We might say in this case that – S is reachable at level 0, – a and B at level 1, – b and C at level 2, – and c at level 3.

Page 5: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

A second kind of useless symbol

Two simple inductions show that X is reachable iff S =*> X for some strings and of symbols.

A symbol X is also useless iff it cannot derive a string of terminals– that is, iff there's no string w of terminals such that

X =*> w.

Page 6: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Another simplification example

In the grammar with rules– S → aB, B → b|BD|cC, C → cC, D → d

the symbol C cannot derive a string of terminals.

So it and all rules that contain it may be eliminated to get just

S → aB, B → b|BD, D → d

Page 7: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Generating strings of terminals

A simple induction shows that the only symbols that can generate strings of terminals are – terminal symbols– variables A for which A → is a rule of the

grammar and every symbol of generates a string of terminals

Page 8: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Our example revisited

In the grammar above, we would observe– first that a, b, c, and d generate strings of

terminals (at level 0), – then that B and D do (at level 1), – and finally that S does (at level 2)

Page 9: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Removing the two kinds of useless symbols

The characterizations of the two kinds of useless symbols are similar, except that– To find reachable symbols, we work top down– To find generating symbols, we work bottom up.

When removing useless symbols, it’s important to remove unreachable symbols last– since only this order will leave only useful symbols

at the end of the process.

Page 10: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Bad example of removing useless symbols

Using the algorithms implicit in the above characterizations, suppose a CFG has rules– S → aB, B → b|bB|CD, C → cC, D → d

We first observe that a, b, c, and d generate strings of terminals (at level 0)– then that B and D do (at level 1)– and finally that S does (at level 2).

But removing the rule B → CD from this grammar makes the symbol D unreachable.

Page 11: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Eliminating-rules

Sometimes it is desirable to eliminate -rules from a grammar G.

This cannot be done if is in L(G), But it's always possible to eliminate-rules

from a CFG and get a grammar that generates L(G) - {}.

Page 12: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Nullable symbols

Eliminating -rules is like eliminating useless symbols.

We first define a nullable symbol A to be one such that A =*> .

Then for every rule that contains a nullable symbol on the RHS, we add a version of the rule that doesn't contain this symbol.

Finally we remove all -productions from the resulting grammar.

Page 13: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Nullability

Note that is in L(G) iff S is nullable. In this case a CFG with S → as its only -rule

can be obtained by removing all other -rules and then adding this rule.

Otherwise, removing -rules gives a CFG that generates L(G) = L(G) - {}

By a simple induction, A is nullable iff– G has a rule A → , or– G has a rule A → , where every symbol in is nullable

Page 14: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Example: removing nullable symbols

Suppose G has the 9 rules– S → ABC | CDB, A → |aA, B → b|bB, – C → |cC, D → AC

Then A and C are nullable, as is D. Optionally deleting nullable symbols adds:

– S → BC | AB | B, S → DB | CB | B,– A → a, C → c, D → A | C

Removing A → and C → (and not adding D → ) gives a CFG with 16 distinct rules

Page 15: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Observations on the previous example

Note that if the rule S → ABC had been replaced by S → AC, then would be in L(G).

We’d then have to allow the rule S → into the simplified grammar to generate all of L(G).

Our algorithm for eliminating -rules has the annoying property that it introduces rules with a single variable on the RHS

Page 16: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Unit productions

Productions of the form A → B are called unit productions.

Unit productions can be eliminated from a CFG

In all cases where A =*> B => a rule must be added of the form A →

Page 17: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

When does A =*> B ?

This requires finding all cases where A =*> B for nonterminals A and B

But a version of our usual BFS algorithm will do the trick: we have that A =*> B iff– A → B is a rule of the grammar, or– A → C is a rule of the grammar, and C =*>B

The =*> relation may be represented in a dependency graph

Page 18: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Eliminating unit productions -- example

Consider the familiar grammar with rules– E → E+T | T, T → T*F | F, F → x | (E)

Here we have that– E =*> T and T =*> F (at level 0), and – E =*> F (at level 1)

Eliminating unit productions gives new rules– E → E+T | T*F | x | (E)– T → T*F | x | (E)– F → x | (E)

Page 19: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Order of steps when simplifying

To eliminate useless symbols, -productions, and unit productions safely from a CFG, we need to apply the simplification algorithms in an appropriate order.

A safe order is: -productions – unit productions– useless symbols

nongenerating symbols unreachable symbols

Page 20: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Chomsky normal form

One additional way to simplify a CFG is to simplify each RHS

A CFG is in Chomsky normal form (CNF) iff each production has a RHS that consists of– a single terminal symbol, or– two variable symbols

Fact: for any CFG G, with not in L(G), there is an equivalent grammar G1 in CNF.

Page 21: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Converting to Chomsky normal form

A CFG that doesn't generate may be converted to CNF by first eliminating all -moves and unit productions.

This will give a grammar where each RHS of length less than 2 consists of a lone terminal.

Any RHS of length k > 2 may be broken up by introducing k-2 new variables.

For any terminal a that remains on a RHS, we add a new variable and new rule Ca → a.

Page 22: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Converting to CNF: an example

For example, the rule S → AbCD in a CFG G can be replaced by– S → AX, X → bY, Y → CD

Here we don’t change L(G) After the remaining steps, the new rules

would be – S → AX, X → CbY, Y → CD, Cb → b

Again we don’t change L(G)

Page 23: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

A more complete example

Consider the grammar with rules– E → E + T | T * F | x, T → T * F | x, F → x

The last rule for each symbol is legal in CNF. We may replace

– E → E + T by E → EX, X → C+T, C+ → +

– E → T * F by E → TY, Y → C*F, C* → *

– T → T * F by T → TZ, Z → C*F, C*→ *

Page 24: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

The resulting grammar

The resulting CFG is in CNF, with rules – E → EX | TY | x– T → TZ | x– F → x– X → C+T

– Y → C*F

– Z → C*F (or Z could be replaced by Y)

– C+ → +

– C* → *

Page 25: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Compact parse trees for CNF grammars

Claim: a parse tree of height n for a CFG in CNF must have a yield of length at most 2n-1.

Note that the number of nodes at level k can be at most twice the number on level k-1, – giving a maximum of 2k nodes at level k for k<n.

And at level n, all nodes are terminals, and for a CFG in CNF they can’t have siblings.

So there are just as many nodes at level n as variables at level n-1– and this number is at most 2n-1.

Page 26: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Parsing and the membership question

It’s common to ask for a CFG G, and a string x, whether x ε L(G)

We already have a nondeterministic algorithm for this question.

For example, we may guess which rules to apply until we have constructed a parse tree yielding x.

Page 27: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

A deterministic membership algorithm

One reasonably efficient membership algorithm (the CYK algorithm) works bottom up.

It's easiest to state for the case when G is in CNF

This assumption about G doesn't result in any loss of generality

But it does make the algorithm more efficient.

Page 28: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

The CYK algorithm

The CYK algorithm asks, for every substring wij of w, which variables generate wij.

Here wij is the substring of w starting at position i and ending at position j.

If i=j (and the grammar is in CNF), we need only check which rules have the correct symbols on their RHS.

Otherwise, we know that the first rule of a derivation for wij must be of the form A → BC

Page 29: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Parsing bottom up with CYK

So we have that A =*> wij iff there are B, C, and k such that – B =*> wik, C =*> w(k+1)j, and

– A → BC is a rule of the grammar

Because the algorithm works bottom up, we already know which variables generate each substring of wij.

The CYK algorithm saves these variables in a 2D table, indexed by i and j.

Page 30: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

The table for CYK parsing

To fill the table entry for wij, we need only – look in the table for the variables that generate wik

– look in the table for those that generate w(k+1)j

– then see which rules of G have on their RHSs a variable from the first group followed by a variable from the second group.

Of course, we need to do this for all possible values of k from i to j-1.

Page 31: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Decoding the CYK table

The algorithm concludes that x is in L(G) iff S is one of the symbols that generates w1n.

This strategy of computing and saving answers to all possible subproblems, without checking whether the subproblems are relevant, is known as dynamic programming.

Page 32: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

A CYK example

The CYK table for G as in Linz, p. 172, and w = bbaab, is given at right

For this example, since S is one of the variables in the table entry for w1n = w, we may say that w is in the language.

i \ j 1 2 3 4 5

1 B A     B,S

2   B     A

3     A   B,S

4       A B,S

5         B

Page 33: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

Parse trees from CYK tables

The table as we have built it does not give a parse tree, or say whether there is more than one.

To recover the parse tree(s), we would have had to save information about how each entry got into the table.

The analog of this observation is true in general for dynamic programming algorithms.

Page 34: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

The parse tree for our CYK example

For the given example, the S in the corner arises only from S → AB with k=2

Continuing with A and B gives the parse tree below S

/ \

A B

/ \ / \

B B A B

| | | / \

b b a A B

| |

a b

Page 35: Simplifying CFGs There are several ways in which context-free grammars can be simplified. One natural way is to eliminate useless symbols – those that

CYK time complexity

If n = |w|, filling each of the n2) table entries takes time O(n), for time O(n3) in all

In fact, CYK takes time (n3), since (j-i) time is needed to fill the i,j entry.

The time complexity also depends on the size of the grammar, since the set of rules must be repeatedly traversed.

CYK takes time (n2) on an unambiguous CFG