Natural and Context-free Languages (CFLs)/Ambiguity contest

profileRony
Chapter15ContextfreeParsing.ppt

Parsing

Chapter 15

The Job of a Parser

  • Examine a string and decide whether or not it is a syntactically well-formed member of L(G), and
  • If it is, assign to it a parse tree that describes its structure and thus can be used as the basis for further interpretation.

Given a context-free grammar G:

Problems with Solutions So Far

  • We want to use a natural grammar that will produce a natural parse tree. But:

decideCFLusingGrammar, requires a grammar that is in Chomsky normal form.

decideCFLusingPDA, requires a grammar that is in Greibach normal form.

  • We want an efficient parser. But both procedures require search and take time that grows exponentially in the length of the input string.
  • All either procedure does is to determine membership in L(G). It does not produce parse trees.

Easy Issues

  • Actually building parse trees: Augment the parser with a function that builds a chunk of tree every time a rule is applied.
  • Using lookahead to reduce nondeterminism: It is often possible to reduce (or even eliminate) nondeterminism by allowing the parser to look ahead at the next one or more input symbols before it makes a decision about what to do.

Dividing the Process

  • Lexical analysis:

done in linear time with a DFSM

  • Parsing:

done in, at worst O(n3) time.

Lexical Analysis

level = observation - 17.5;

Lexical analysis produces a stream of tokens:


id = id - id

Specifying id with a Grammar

id  identifier | integer | float

identifier  letter alphanum

alphanum  letter alphnum | digit alphnum | 

integer  - unsignedint | unsignedint

unsignedint  digit | digit unsignedint

digit  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

….

Using Reg Ex’s to Specify an FSM

There exist simple tools for building lexical analyzers.

The first important such tool: Lex

Lex Rules

Get rid of blanks and tabs:

[ \t]+;

Find identifiers:

[A-Za-z][A-Za-z0-9]* {return(ID); }

Return INTEGER and save a value:

[0-9]+ {sscanf(yytext, "%d", &yylval);

return (INTEGER); }

Dealing with Rule Conflicts

  • A longer match is preferred over a shorter one.
  • When lengths are equal, choose the first one.

Suppose that Lex has been give the following two rules:

integer {action 1}

[a-z]+ {action 2}

Example 1: integers

Example 2: integer

Parsing

  • Top-down parsers:

A simple but inefficient recursive descent parser.

Modifying a grammar for top-down parsing.

LL parsing.

  • Bottom-up parsers:

The simple but not efficient enough Cocke-Kasami-Younger (CKY) algorithm.

LR parsing.

  • Parsers for English and other natural languages.

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Fail

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Backup to:

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Top-Down, Depth-First Parsing

S  NP VP $

NP  the N | N | ProperNoun

N  cat | dogs | bear | girl | chocolate | rifle

ProperNoun  Chris | Fluffy

VP  V | V NP

V  like | likes | thinks | shot | smells

Input: the cat likes chocolate $

Built,

unbuilt,

built again

Building and Discarding Subtrees

NP  the Nominal | Nominal | ProperNoun | NP PP

Nominal  N | Adjs N

Adjs  Adv Adjs | Adjs and Adjs | Adj Adjs | Adj

N  student | raincoat

Adj  tall | self-possessed | green

Adv  strikingly

PP  Prep NP

Prep  with

the strikingly tall and self-possessed student with the

green raincoat

Left-Recursive Rules

E  E + T

E  T

T  T  F

T  F

F  (E)

F  id

On input: id + id + id :

Then:

And so forth.

Removing Left-Recursive Rules

Original left-recursive rules: Replace with:
A  A1 A'  1A'
A  A2 A'  2A'
A  An A'  nA'
A'  
Original nonleft-recursive rules: Replace with:
A  1 A  1A'
A  2 A  2A'
A  m A  mA'

Modifying the Expression Grammar

E  T E

E  + T E

E  

T  F T

T   F T

T  

F  (E)

F  id

E  E + T

E  T

T  T  F

T  F

F  (E)

F  id

becomes

Indirect Left Recursion

S  Ya

Y  Sa

Y  

This form too can be eliminated.

But There is a Price

Using Lookahead and Left Factoring

  • Change the parsing algorithm so that it exploits the ability to look one symbol ahead in the input before it makes a decision about what to do next, and
  • Change the grammar to help the parser procrastinate decisions.

Goal: Procrastinate branching as long as possible. To do that, we will:

Exploiting Lookahead

(1) F  (E)

(2) F  id

(3) F  id(E)

Looking ahead one character makes it possible to choose between rule (1) and rules(2)/(3).

But how is it possible to choose between (2) and (3)?

Left Factoring

(1) F  (E)

(2) F  id

(3) F  id(E)

becomes

(1) F  (E)

(1.5) F  id X

(2) X  

(3) X  (E)

More generally:

A  1

A  2

A  n

becomes

A  A'

A'  1

A'  2

A'  n

Predictive Parsing

It will be possible to build a predictive top-down parser for a grammar G iff:

  • Every string that is generated by G has a unique

left-most derivation, and

  • It is possible to determine each step in that derivation by

looking ahead some fixed number k of characters.

In this case, we say that G is LL(k).

LL(k) Grammars

An LL(k) grammar allows a predictive parser:

  • that scans its input Left to right
  • to build a Left-most derivation
  • if it is allowed k lookahead symbols.

Every LL(k) grammar is unambiguous (because every string it generates has a unique left-most derivation).

But not every unambiguous grammar is LL(k).

Two Important Functions

  • first() is the set of terminal symbols that can occur as the first symbol in any string derived from  using RG. If  derives , then   first().
  • follow(A) is the set of all terminal symbols that can immediately follow whatever A produces in some string in L(G).

Computing First and Follow

S  AXB$

A  aA | 

X  c | 

B  bB | 


first(S) = {a, c, b, $}.

first(A) = {a, }.

first(AX) = {a, c, }.

first(AXB) = {a, c, b, }.


follow(S) = .

follow(A) = {c, b, $}.

follow(X) = {b, $}.

follow(B) = {$}.

When is a Grammar LL(1)?

  • No terminal symbol is an element of both first() and first().
  •  cannot be derived from both of  and .
  • If  can be derived from one of  or , assume it is . Then there may be two competing derivations:

S  1 A 2 and S  1 A 2

 1  2  1  2

 1 2

So there must be no terminal symbol that is an element of both follow(A) and first().

Whenever G contains two competing rules A   and

A  , all of the following are true:

Not Every CF Language is LL(k)

  • No inherently ambiguous language is LL(k).
  • Some others aren’t either:

{anbncmd : n, m  0}  {anbmcme : n, m  0}

{anbn, n  0}  {ancn, n  0} (deterministic CF)

Recursive Descent Parsing

A  BA | a

B  bB | b

A(n: parse tree node labeled A) =

case (lookahead = b : /* Use A  BA.

Invoke B on a new daughter node labeled B.

Invoke A on a new daughter node labeled A.

lookahead = a : /* Use A  a.

Create a new daughter node labeled a.

Table-Driven LL(1) Parsing

S  AB$ | AC$

A  aA | a

B  bB | b

C  c

Lookahead symbol Top of stack a b c $
S S  AB$ S  AC$
A A  aA A  a
B B  bB B  b
C C  c

Bottom-Up Parsing

  • Cocke-Kasami-Younger (CKY)
  • Shift-reduce parsing
  • LR(1) parsing

CKY

Row 5

Row 4

Row 3

Row 2

Row 1

id + id  id

  • Bottom-up
  • Chart parser
  • Dynamic programming
  • Grammar in Chomsky Normal form
id + id  id
id + id  + id  id
id + id + id  id  id
id + + id id   id
id + id id

Exploiting Chomsky Normal Form

All rules have one of the following two forms:

  • X  a, where a  , or
  • X  BC, where B and C are elements of V - .

So we need two techniques for filling in T:

  • To fill in row 1, use rules of the form X  a.
  • To fill in rows 2 through n, use rules of the form X  BC.

The CKY Algorithm

/* Fill in the first (bottom-most) row of T.

For j = 1 to n do:

If G contains the rule X  aj, then add X to T[1, j].

/* Fill in the remaining rows, starting with row 2.

For i = 2 to n do:

For j = 1 to n-i+1 do:

For k = 1 to i-1 do:

For each rule X  YZ do:

If Y  T[k, j] and Z  T[i-k, j+k], then: ####

Insert X into T[i, j].

If SG  T[n, 1] then accept else reject.

A CKY Example

Consider parsing the string aab with the grammar:

S  A B

A  A A

A  a

B  a

B  b

CKY begins by filling in the bottom row of T as follows:

a a b

Row 3

Row 2

Row 1

Input string

A, B A, B B

A CKY Example

S  A B

A  A A

A  a

B  a

B  b

a a b

Row 3

Row 2

Row 1

Input string

S, A S
A, B A, B B

The Complexity of CKY

/* Fill in the first (bottom-most) row of T.

For j = 1 to n do:

If G contains the rule X  aj, then add X to T[1, j].

/* Fill in the remaining rows, starting with row 2.

For i = 2 to n do:

For j = 1 to n-i+1 do:

For k = 1 to i-1 do:

For each rule X  YZ do:

If Y  T[k, j] and Z  T[i-k, j+k], then:

Insert X into T[i, j].

If SG  T[n, 1] then accept else reject.

O(n)

n – 1

n/2

n/2

O(|G|)

O(1)

O(n3)

Context-Free Parsing and
Matrix Multiplication

  • CF parsing can be described as Boolean matrix multiplication.

Strassen’s algorithm: O(n2.807)

Coppersmith-Winograd algorithm O(n2.376)

  • Boolean matrix multiplication can be described as CF-parsing.

If P is a O(gn3-) CF parser, then P can be efficiently converted into a O(n3-/3) matrix multiplier.

Shift-Reduce Parsing

  • Shift an input symbol onto the parser’s stack and build, in the parse tree, a terminal node labeled with that input symbol.
  • Reduce a string of symbols from the top of the stack to a nonterminal symbol, using one of the rules of the grammar. Each time it does this, it also builds the corresponding piece of the parse tree.

A bottom-up left-to-right parser that can do two things:

A Shift-Reduce Example

Parse: id + id  id

Using:

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

A Shift-Reduce Example

(1) E  E + T

(2) E  T

(3) T  T * F

(4) T  F

(5) F  (E)

(6) F  id

id + id  id

Making Decisions

  • Shift-reduce conflicts
  • Reduce-reduce conflicts

Shift-Reduce Conflicts

  • The symbol that is currently on the top of the stack, coupled with a good understanding of what is going on in the grammar.

  • A peek at the lookahead symbol. In order to guarantee that there always is a lookahead symbol, we’ll assume that every string ends with $.

To resolve them, we use two pieces of information:

Precedence Relations

Define P  V  {  $}:

P will contain the pair (s, c) iff, whenever the top of stack symbol is s and the lookahead symbol is c, the parser should reduce.

If the current situation is described by a pair that is not in P, then the parser will shift the lookahead symbol onto the stack.

Precedence Tables

Storing the precedence relation for the expression grammar:

( ) id + $
(
) R R R R
id R R R R
+
*
E
T R R R
F R R R R

Using the Precedence Table

id + id  id

No R in (T, ).

But suppose the lookahead symbol were +:

Reduce-Reduce Conflicts

The longest prefix heuristic:

LR(k) Grammars

G is LR(k), for any positive integer k, iff it is possible to build a deterministic parser for G that:

  • scans its input Left to right and,
  • for any input string in L(G), builds a Rightmost derivation,
  • looking ahead at most k symbols.

A language is LR(k) iff there is an LR(k) grammar for it.

LR(k) Grammars

  • The class of LR(k) languages is exactly the class of deterministic context-free languages.
  • If a language is LR(k), for some k, then it is also LR(1).

Parsing Natural Languages

  • Ambiguity
  • Gaps
  • Dialect
  • Evolution
  • Errors
  • Agreement

Ambiguity

Ambiguity

Ambiguity

Ambiguity

Gaps

How to build a meaningful parse tree for:

What did Will say he ate for lunch?

Evolution

  • The lady doth protest too much, methinks.

  • You wanted to do that why?
  • They’re open 24/7.

Agreement

Chris likes the cat.

* The dogs likes the cat.

The girl likes herself.

* The girl likes himself.

This cat likes chocolate.

* These cat likes chocolate.

The cat likes chocolate.

* The cat sleeps chocolate.

The Earley Algorithm

  • Top-down
  • Chart parser
  • Uses dynamic programming: It builds each constituent only once.

The  Notation

A  

A  

A  

Describes an attempt to apply the rule A  , where everything before the  has already matched against the input and the parser is still trying match everything after the .

Describes a similar attempt except that nothing has yet matched against the input.

Describes a similar attempt except that the entire right-hand side (and thus also A) has matched against the input.

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2
1
0 S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2
1
0 NP   ProperNoun [0, 0] S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2
1 ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0] S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2
1 S NP  VP [0, 1] NP ProperNoun  [0, 1] ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0]  S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2
1 VP  V NP [1, 1]  S NP  VP [0, 1] NP ProperNoun  [0, 1] ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0]  S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3
2 V saw  [1, 2]
1  VP  V NP [1, 1]  S NP  VP [0, 1] NP ProperNoun  [0, 1] ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0]  S   NP VP [0, 0]

An Earley Example

S  NP VP

NP  ProperNoun

VP  V NP

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3 ProperNoun Bill  [2, 3]
2  NP  ProperNoun [2, 2]  VP V  NP [1, 2]  V saw  [1, 2]
1  VP  V NP [1, 1]  S NP  VP [0, 1] NP ProperNoun  [0, 1] ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0]  S   NP VP [0, 0]

An Earley Example

ProperNoun V, N ProperNoun

0 Jen 1 saw 2 Bill 3

3 S NP VP  [0, 3]  VP V NP  [1, 3]  NP ProperNoun  [1, 2]  ProperNoun Bill  [2, 3]
2  NP  ProperNoun [2, 2]  VP V  NP [1, 2]  V saw  [1, 2]
1  VP  V NP [1, 1]  S NP  VP [0, 1] NP ProperNoun  [0, 1] ProperNoun Jen  [0, 1]
0 NP   ProperNoun [0, 0]  S   NP VP [0, 0]

Earleyparse

For every rule in G of the form S  , where S is the start symbol of G, do: /* Initialize chart.

insert(chart, S    [0, 0]).

For i = 0 to n do:

For each rule r in rowi of chart do:

If r corresponds to finding a complete

constituent, then extendothers(chart, r).

Else if the symbol after the  of r is a part of

speech tag, then scaninput(w, chart, r).

Else predict(chart, r).

Earleyparse

insert(chart, r [j, k]: rule that spans from j to k in chart) =

If r is not already on chart, spanning from j to k, then: add it in row k.

extendothers(chart: chart, r [j, k]: rule of the form:

A    that spans from j to k in chart) =

For each rule p of the form X    A  [i, j] on chart do: /* Find rules waiting for A starting at j.

insert(chart, X   A   [i, k]).

Earleyparse

scaninput(w: input string, chart: chart, r [j, k]: rule of the

form A    A , where A is a part of speech tag,

and the rule spans from j to k in chart ) =

If wk has been labeled with the tag A then:

insert(chart, A  wk  [k, k+1]).

predict(chart: chart, r [j, k]: rule of the form A    B 

that spans from j to k in chart) =

For each rule in G of the form B   do:

insert(chart, B    [k, k]).