Computer Science 301 - 2005

Extra tutorials for Swot Week (4) - LL(1) conditions and rewritten EBNF

Rewrite the following grammars so as to eliminate the Wirth meta-brackets { } and [ ] and hence (or otherwise) test the grammars for being LL(1) compliant. If they are not LL(1) compliant, can you find equivalent LL(1) compliant grammars?

You can find the sources for these grammars in the file tut31.zip.


Grammar 1

  COMPILER Course
  /* Grammar describing history of a university course */

  PRODUCTIONS
    Course          = Introduction Section { Section } Conclusion .
    Introduction    = "lecture" [ "handout" ] .
    Section         = { "lecture" | "practical" "test" | "tutorial" | "handout" } "test" .
    Conclusion      = [ "panic" ] "examination" .
  END Course.

Change the PRODUCTIONS section to read

  PRODUCTIONS
    Course          = Introduction Section MoreSections Conclusion .
    MoreSections    = Section MoreSections | e .
    Introduction    = "lecture" OptionalHandout .
    OptionalHandout = "handout" | e .
    Section         = Subsections  "test" .
    Subsections     = Delivery Subsections | e
    Delivery        = "lecture" | "practical" "test" | "tutorial" | "handout"
    Conclusion      = OptionalPanic"examination" .
    OptionalPanic   = "panic" | e .
  END Course.

The grammar is non LL(1). OptionalHandout is nullable, and

    FIRST(OptionalHandout)  = { "handout" }
    FOLLOW(OptionalHandout) = FIRST(Section)
                            = { "lecture" , "practical" "test" , "tutorial" , "handout" }

The other nullable non-terminals do not raise any problems.


Grammar 2

  COMPILER RE
  /* Regular expression grammar */

  CHARACTERS
    control   = CHR(0) .. CHR(31) .
    noquote1  = ANY - control - "'" .
    noquote2  = ANY - control - '"' .
    meta      = "()*,.;[]-?+" .
    simple    = ANY - control - "'" - '"' - meta .
    backslash = CHR(92) .

  TOKENS
    atomic  = simple .
    escaped = "'" noquote1 "'" | '"' noquote2 '"' .

  COMMENTS FROM backslash TO backslash

  IGNORE  control

  PRODUCTIONS
    RE             = { Expression ";" } EOF .
    Expression     = Term { "|" Term } .
    Term           = Factor { [ "." ] Factor } .
    Factor         = Element [ "*" | "?" | "+" ] .
    Element        = Atom | Range | "(" Expression ")" .
    Range          = "[" OneRange { OneRange } "]" .
    OneRange       = Atom [ "-" Atom ] .
    Atom           = atomic | escaped .
  END RE.

Change the PRODUCTIONS section to read

  PRODUCTIONS
    RE             = Expressions EOF .
    Expressions    = Expression ";" Expressions | e .
    Expression     = Term MoreTerms .
    MoreTerms      = "|" Term MoreTerms | e .
    Term           = Factor MoreFactors .
    MoreFactors    = OptionalDot Factor MoreFactors | e .
    OptionalDot    = "." | e .
    Factor         = Element OptionalSuffix .
    OptionalSuffix = "*" | "?" | "+" | e .
    Element        = Atom | Range | "(" Expression ")" .
    Range          = "[" OneRange MoreRanges "]" .
    MoreRanges     = OneRange MoreRanges | e .
    OneRange       = Atom OptionalAtom .
    OptionalAtom   = "-" Atom | e .
    Atom           = atomic | escaped .
  END RE.

This is an LL(1) grammar. The full analysis is easy enough to do.


Grammar 3

  COMPILER Play
  /* Grammar for Shakespearian play */

  PRODUCTIONS
    Play   =  Act Act Act "interval" Act Act .
    Act    =  Scene { Scene } .
    Scene  =  { "speech" } "entry" { Action } .
    Action =  "speech" | "entry" | "exit" | "death" | "gesticulation" .
  END Play.

Change the PRODUCTIONS section to read

  PRODUCTIONS
    Play       = Act Act Act "interval" Act Act .
    Act        = Scene MoreScenes .
    MoreScenes = Scene MoreScenes | e .
    Scene      = Speeches "entry" Actions .
    Speeches   = "speech" Speeches | e .
    Actions    = Action Actions | e .
    Action     = "speech" | "entry" | "exit" | "death" | "gesticulation" .
  END Play.

Here MoreScenes, Speeches and Actions are nullable

   FIRST(MoreScenes) = { "speech", "entry" }
   FOLLOW(MoreScenes) = FOLLOW(Act)
                      = First(Act) U { "interval" }
                      = FIRST(Scene) U { "interval" } = { "speech", "entry", "interval" }

so the grammar is non-LL(1).

   FIRST(Speeches)  = { "speech" }
   FOLLOW(Speeches) = { "entry" }

so no problem there

   FIRST(Actions)   = { "entry", "speech",  "exit",  "death",  "gesticulation" }
   FOLLOW(Actions)  = Follow(Scene) = { "interval", "entry", "speech" }

so the grammar is non-LL(1) there as well.

Ignoring any LL(1) problems - how would you attribute this last grammar to check that there were no actors left on the stage at the end of every act?

The only way to "fix" this probably is to have some sort of extra visual cue - like curtains or lights being raised and lowered to mark one scene or act from another.

Clearly this won't work, properly, but the idea would be

  COMPILER Play
  /* Grammar for Shakespearian play */

  int onStage = 0; /* can get away with a global count */

  PRODUCTIONS
    Play
    =  Act Act Act "interval" Act Act .

    Act                        (. onStage = 0; .)
    =  Scene { Scene }         (. if (onstage > 0) SemError("some actors are still on stage"); .)
    .

    Scene
    =  { "speech" } "entry"    (. onstage++; .)
       { Action } .

    Action
    =    "speech"
       | "entry"               (. onstage++; .)
       | "exit"                (. onstage--;
                                  if (onStage < 0) SemError("more actors have left than have entered"); .)
       | "death"
       | "gesticulation" .

  END Play.


Home  © P.D. Terry