1 / 32

Lesson 4

Lesson 4. CDT301 – Compiler Theory , Spring 2011 Teacher : Linus Källberg. Outline. Recursive descent parsers Left recursion Left factoring. Recursive descent parsing. Writing a recursive descent parser. Straightforward once the grammar is written in an appropriate form:

alban
Télécharger la présentation

Lesson 4

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lesson 4 CDT301 – CompilerTheory, Spring 2011 Teacher: Linus Källberg

  2. Outline • Recursive descent parsers • Left recursion • Left factoring

  3. Recursive descent parsing

  4. Writing a recursivedescent parser • Straightforward once the grammar is written in an appropriate form: • For each nonterminal: create a function • Represents the expectation of that nonterminal in the input • Each such function should choose a grammar production, i.e., RHS, based on the lookahead token • It should then process the chosen RHS • Terminals are “matched”: match(IF);match(LEFT_PARENTHESIS); … match(RIGHT_PARENTHESIS); … • For nonterminals their corresponding “expectation functions” are called

  5. The function match() • Helper function to consume terminals: void match(intexpected_lookahead) { if (lookahead == expected_lookahead) lookahead = nextToken(); else error(); } (assumes tokens are represented as ints)

  6. Recursive descent example • Grammar for a subset of the language “types in Pascal”: type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num • Examples of “programs”: ^ my_type array[ 1..10 ] of Integer array[ Char ] of 72..98

  7. Recursive descent example void type() { switch(lookahead) { case '^': match('^'); match(ID); break; case ARRAY: match(ARRAY); match('['); simple(); match(']'); match(OF); type(); break; default: simple(); } } void simple() { switch(lookahead) { caseINTEGER: match(INTEGER); break; case CHAR: match(CHAR); break; caseNUM: match(NUM); match(DOTDOT); match(NUM); break; default: error(); } }

  8. Exercise (1) List the calls made by the previous recursive descent parser on the input string array [ num dotdot num ] of integer To get you started: type() match(ARRAY) match('[') simple() ...

  9. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type array [numdotdotnum] of integer

  10. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum] of integer

  11. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  12. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  13. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  14. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  15. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  16. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  17. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  18. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type array [numdotdotnum]of integer

  19. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type simple array [numdotdotnum]of integer

  20. type → ^ id | array [ simple ] of type | simple simple → integer | char | num dotdot num type simple type simple array [numdotdotnum]of integer

  21. Left recursion

  22. The problem with left recursion • Left-recursive grammar: A → A α | β • Problematic for recursive descent parsing • Infinite recursion

  23. The problem with left recursion • The left-recursive expression grammar: expr → expr + num | expr – num | num • Parser code: voidexpr() { if (lookahead != NUM) expr(); match('+'); …

  24. Eliminating left recursion • Left-recursive grammar: A → A α | β • Rewritten grammar: A → β M M → α M | ε

  25. Exercise (2) Remove the left recursion from the following grammar for formal parameter lists in C: list → par | list , par par → int id int and id are tokens that represent the keyword int and identifiers, respectively. Hint: what is α and what is β in this case?

  26. Left factoring

  27. The problem • Recall: how does a predictive parser choose production body? • What if the lookahead token matches more than one such production body?

  28. The problem • Problematic grammar: list → num | num , list • If lookahead = num, what to expect?

  29. Left factoring • The previous grammar, list → num | num, list becomes list → numlist’ list’ → ε | , list

  30. Exercise (3) Perform left factoring on the following grammar for declarations of variables and functions in C: decl → intid ; | intid ( pars ) ; pars → ...

  31. Conclusion • Recursive descent parsers • Left recursion • Left factoring

  32. Next time • The sets firstand follow • Defining LL(1) grammars • Non-recursive top-down parser • Handling syntax errors

More Related