CS Parsing 1

Similar documents
Note that for recursive descent to work, if A ::= B1 B2 is a grammar rule we need First k (B1) disjoint from First k (B2).

Types of parsing. CMSC 430 Lecture 4, Page 1

Administrativia. WA1 due on Thu PA2 in a week. Building a Parser III. Slides on the web site. CS164 3:30-5:00 TT 10 Evans.

CS1622. Today. A Recursive Descent Parser. Preliminaries. Lecture 9 Parsing (4)

Building a Parser III. CS164 3:30-5:00 TT 10 Evans. Prof. Bodik CS 164 Lecture 6 1

1 Introduction. 2 Recursive descent parsing. Predicative parsing. Computer Language Implementation Lecture Note 3 February 4, 2004

Abstract Syntax Trees & Top-Down Parsing

Ambiguity, Precedence, Associativity & Top-Down Parsing. Lecture 9-10

Abstract Syntax Trees & Top-Down Parsing

Abstract Syntax Trees & Top-Down Parsing

Compilers. Predictive Parsing. Alex Aiken

Top-Down Parsing and Intro to Bottom-Up Parsing. Lecture 7

Top-Down Parsing and Intro to Bottom-Up Parsing. Lecture 7

Top down vs. bottom up parsing

CS 132 Compiler Construction, Fall 2012 Instructor: Jens Palsberg Multiple Choice Exam, Nov 6, 2012

Parsing Part II (Top-down parsing, left-recursion removal)

CMSC 330: Organization of Programming Languages

8 Parsing. Parsing. Top Down Parsing Methods. Parsing complexity. Top down vs. bottom up parsing. Top down vs. bottom up parsing

CS502: Compilers & Programming Systems

EDA180: Compiler Construc6on. Top- down parsing. Görel Hedin Revised: a

Ambiguity. Grammar E E + E E * E ( E ) int. The string int * int + int has two parse trees. * int

Syntax Analysis. Martin Sulzmann. Martin Sulzmann Syntax Analysis 1 / 38

CS 164 Programming Languages and Compilers Handout 9. Midterm I Solution

Extra Credit Question

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

3. Parsing. Oscar Nierstrasz

PESIT Bangalore South Campus Hosur road, 1km before Electronic City, Bengaluru -100 Department of Computer Science and Engineering

CPS 506 Comparative Programming Languages. Syntax Specification

Parsing. Roadmap. > Context-free grammars > Derivations and precedence > Top-down parsing > Left-recursion > Look-ahead > Table-driven parsing

Course Overview. Introduction (Chapter 1) Compiler Frontend: Today. Compiler Backend:

CSCI312 Principles of Programming Languages

Compilers. Yannis Smaragdakis, U. Athens (original slides by Sam

Syntax Analysis. COMP 524: Programming Language Concepts Björn B. Brandenburg. The University of North Carolina at Chapel Hill

Chapter 3. Parsing #1

Syntax Analysis. The Big Picture. The Big Picture. COMP 524: Programming Languages Srinivas Krishnan January 25, 2011

CS2210: Compiler Construction Syntax Analysis Syntax Analysis

Syntactic Analysis. Top-Down Parsing

Compilation Lecture 3: Syntax Analysis: Top-Down parsing. Noam Rinetzky


COP4020 Programming Languages. Syntax Prof. Robert van Engelen

CA Compiler Construction

Syntactic Analysis. Chapter 4. Compiler Construction Syntactic Analysis 1

More Bottom-Up Parsing

Parsing #1. Leonidas Fegaras. CSE 5317/4305 L3: Parsing #1 1

Table-driven using an explicit stack (no recursion!). Stack can be viewed as containing both terminals and non-terminals.

Computing PREDICT and FOLLOW sets

CS143 Midterm Sample Solution Fall 2010

Lecture Notes on Top-Down Predictive LL Parsing

Topdown parsing with backtracking

CS 321 Programming Languages and Compilers. VI. Parsing

Outline. Top Down Parsing. SLL(1) Parsing. Where We Are 1/24/2013

Structure of JavaCC File. JavaCC Rules. Lookahead. Example JavaCC File. JavaCC rules correspond to EBNF rules. JavaCC rules have the form:

COP4020 Programming Languages. Syntax Prof. Robert van Engelen

Table-Driven Parsing

Compila(on (Semester A, 2013/14)

Syntax Analysis, III Comp 412

Compilerconstructie. najaar Rudy van Vliet kamer 140 Snellius, tel rvvliet(at)liacs(dot)nl. college 3, vrijdag 22 september 2017

Compilers CS S-01 Compiler Basics & Lexical Analysis

Part 3. Syntax analysis. Syntax analysis 96

Chapter 3: Describing Syntax and Semantics. Introduction Formal methods of describing syntax (BNF)

CS 2210 Sample Midterm. 1. Determine if each of the following claims is true (T) or false (F).

JavaCC Rules. Structure of JavaCC File. JavaCC rules correspond to EBNF rules. JavaCC rules have the form:

JavaCC Parser. The Compilation Task. Automated? JavaCC Parser

Outline. 1 Introduction. 2 Context-free Grammars and Languages. 3 Top-down Deterministic Parsing. 4 Bottom-up Deterministic Parsing

Topic 3: Syntax Analysis I

Part III : Parsing. From Regular to Context-Free Grammars. Deriving a Parser from a Context-Free Grammar. Scanners and Parsers.

Compilers CS S-01 Compiler Basics & Lexical Analysis

Fall Compiler Principles Lecture 3: Parsing part 2. Roman Manevich Ben-Gurion University

CSC 4181 Compiler Construction. Parsing. Outline. Introduction

Compiler Design 1. Top-Down Parsing. Goutam Biswas. Lect 5

Syntax Analyzer --- Parser

shift-reduce parsing

4 (c) parsing. Parsing. Top down vs. bo5om up parsing

CS 536 Midterm Exam Spring 2013

Chapter 2 Syntax Analysis

Fall Compiler Principles Lecture 2: LL parsing. Roman Manevich Ben-Gurion University of the Negev

Parsing. Note by Baris Aktemur: Our slides are adapted from Cooper and Torczon s slides that they prepared for COMP 412 at Rice.

Monday, September 13, Parsers

Syntax Analysis, III Comp 412

Midterm I (Solutions) CS164, Spring 2002

CSE431 Translation of Computer Languages

Chapter 4: Syntax Analyzer

3. Parsing. 3.1 Context-Free Grammars and Push-Down Automata 3.2 Recursive Descent Parsing 3.3 LL(1) Property 3.4 Error Handling

COMP 181. Prelude. Next step. Parsing. Study of parsing. Specifying syntax with a grammar

Defining syntax using CFGs

Lexical and Syntax Analysis. Top-Down Parsing

Compilers: CS31003 Computer Sc & Engg: IIT Kharagpur 1. Top-Down Parsing. Lect 5. Goutam Biswas

LL parsing Nullable, FIRST, and FOLLOW

Wednesday, September 9, 15. Parsers

Parsers. What is a parser. Languages. Agenda. Terminology. Languages. A parser has two jobs:

Lexical and Syntax Analysis

CS S-01 Compiler Basics & Lexical Analysis 1

Parsing III. (Top-down parsing: recursive descent & LL(1) )

Compiler construction lecture 3

COP 3402 Systems Software Top Down Parsing (Recursive Descent)

Parsing. Earley Parsing. Laura Kallmeyer. Winter 2017/18. Heinrich-Heine-Universität Düsseldorf 1 / 39

Parsing. Lecture 11: Parsing. Recursive Descent Parser. Arithmetic grammar. - drops irrelevant details from parse tree

Prelude COMP 181 Tufts University Computer Science Last time Grammar issues Key structure meaning Tufts University Computer Science

VIVA QUESTIONS WITH ANSWERS

Introduction to parsers

Transcription:

CS414-20034-03 Parsing 1 03-0: Parsing Once we have broken an input file into a sequence of tokens, the next step is to determine if that sequence of tokens forms a syntactically correct program parsing Parsing a sequence of tokens == determining if the string of tokens could be generated by a Context-Free Grammar. 03-1: CFG Example S print(e); S while (E) S S L E identifier E integer literal L SL L ɛ Examples / Parse Trees 03-2: Recursive Descent Parser Write Java code that repeatedly calls getnexttoken(), and determines if the stream of returned tokens can be generated by the CFG If so, end normally If not, call an error function 03-3: Recursive Descent Parser A Recursive Descent Parser is implemented as a suite of recursive functions, one for each non-terminal in the grammar: ParseS will terminate normally if the next tokens in the input stream can be derived from the non-terminal S ParseL will terminate normally if the next tokens in the input stream can be derived from the non-terminal L ParseE will terminate normally if the next tokens in the input stream can be derived from the non-terminal E 03-4: Recursive Descent Parser S print(e); S while (E) S S L E identifier E integer literal L SL L ɛ Code fore Parser.java.html on web browser 03-5: LL(1) Parsers These recursive descent parsers are also known as LL(1) parsers, for Left-to-right, Leftmost derivation, with 1 symbol lookahead The input file is read from left to right (starting with the first symbol in the input stream, and proceeding to the last symbol). The parser ensures that a string can be derived by the grammar by building a leftmost derivation.

CS414-20034-03 Parsing 2 Which rule to apply at each step is decided upon after looking at just 1 symbol. 03-6: Building LL(1) Parsers S S$ S AB S Ch A ef A ɛ B hg ParseS use rule S AB on e, h use the rule S Ch on f, g 03-7: First sets First(S) is the set of all terminals that can start strings derived from S (plus ɛ, if S can produce ɛ) S S$ First(S ) = S AB First(S) = S Ch First(A) = A ef First(B) = A ɛ First(C) = B hg First(D) = 03-8: First sets First(S) is the set of all terminals that can start strings derived from S (plus ɛ, if S can produce ɛ) S S$ First(S ) = e, f, g, h S AB First(S) = e, f, g, h S Ch First(A) = e, ɛ A ef First(B) = h A ɛ First(C) = f, g B hg First(D) = g 03-9: First sets We can expand the definition of First sets to include strings of terminals and non-terminals S S$ First(aB) = S AB First(BC) = S Ch First(AbC) = A ef First(AC) = A ɛ First(abS) = B hg First(DDA) = 03-10: First sets We can expand the definition of First sets to include strings of terminals and non-terminals

CS414-20034-03 Parsing 3 S S$ First(aB) = a S AB First(BC) = h S Ch First(AbC) = e, b A ef First(AC) = e, f, g A ɛ First(abS) = a B hg First(DDA) = g 03-11: Calculating First sets For each non-terminal S, set First(S) = For each rule of the form S γ, add First(γ) to First(S) Repeat until no changes are made 03-12: Calculating First sets Example: S S$ S AB S Ch A ef A ɛ B hg 03-13: Follow Sets Follow(S) is the set of all terminals that can follow S in a (partial) derivation. S S$ Follow(S ) = S AB Follow(S) = S Ch Follow(A) = A ef Follow(B) = A ɛ Follow(C) = B hg Follow(D) = 03-14: Follow Sets Follow(S) is the set of all terminals that can follow S in a (partial) derivation. S S$ Follow(S ) = S AB Follow(S) = $ S Ch Follow(A) = h A ef Follow(B) = $ A ɛ Follow(C) = h B hg Follow(D) = h, g

CS414-20034-03 Parsing 4 03-15: Calculating Follow sets For each non-terminal S, set Follow(S) = For each rule of the form S γ For each non-terminal S 1 in γ, where γ is of the form αs 1 β If First(β) does not contain ɛ, add all elements of First(β) to Follow(S 1 ). If First(β) does contain ɛ, add all elements of First(β) except ɛ to Follow(S 1 ), and add all elements of Follow(S) to Follow(S 1 ). If any changes were made, repeat. 03-16: Calculating Follow sets Example: S S$ S AB S Ch A ef A ɛ B hg 03-17: Parse Tables Each row in a parse table is labeled with a non-terminal Each column in a parse table is labeled with a terminal Each element in a parse table is either empty, or contains a grammar rule Rule S γ goes in row S, in all columns of First(γ). If First(γ) contains ɛ, then the rule S γ goes in row S, in all columns of Follow(S). 03-18: Parse Table Example S S$ First(S ) = e, f, g, h Follow(S ) = S AB First(S) = e, f, g, h Follow(S) = $ S Ch First(A) = e, ɛ Follow(A) = h A ef First(B) = h Follow(B) = $ A ɛ First(C) = f, g Follow(C) = h B hg First(D) = g Follow(D) = h, g 03-19: Parse Table Example e f g h i S S S$ S S$ S S$ S S$ S S AB S Ch S Ch S AB A A ef A ɛ 03-20: Parse Table Example B B hg C D

CS414-20034-03 Parsing 5 void ParseA() void ParseC() switch(currenttoken) switch(currenttoken) case e: case f: checktoken(e); checktoken(f); checktoken(f); checktoken(i); break; break; case h: case g: /* epsilon case */ ParseD(); break; ParseD(); otherwise: break; error("parse Error"); otherwise: error("parse Error"); 03-21: LL(1) Parser Example Z Z$ Z XY Z d X a Y Y ɛ c (Initial Symbol = Z ) 03-22: LL(1) Parser Example Z Z$ First(Z ) = a, c, d Z XY Z d First(Z) = a, c, d X a Y First(X) = a, c, ɛ Y ɛ c First(Y ) = c, ɛ (Initial Symbol = Z ) 03-23: LL(1) Parser Example Z Z$ First(Z ) = a, c, d Follow(Z ) = Z XY Z d First(Z) = a, c, d Follow(Z) = $ X a Y First(X) = a, c, ɛ Follow(X) = a, c, d Y ɛ c First(Y ) = c, ɛ Follow(Y ) = a, c, d (Initial Symbol = Z ) 03-24: LL(1) Parser Example Z Z$ First(Z ) = a, c, d Follow(Z ) = Z XY Z d First(Z) = a, c, d Follow(Z) = $ X a Y First(X) = a, c, ɛ Follow(X) = a, c, d Y ɛ c First(Y ) = c, ɛ Follow(Y ) = a, c, d a c d Z Z Z$ Z Z$ Z Z$ Z Z XY Z Z XY Z Z XY Z Z d X X a X Y X Y X Y Y Y ɛ Y c Y ɛ Y ɛ 03-25: non-ll(1) Grammars Not all grammars can be parsed by a LL(1) parser A grammar is LL(1) if the LL(1) parse table contains no duplicate entires Previous CFG is not LL(1) 03-26: non-ll(1) Grammars Not all grammars can be parsed by a LL(1) parser A grammar is LL(1) if the LL(1) parse table contains no duplicate entires

CS414-20034-03 Parsing 6 Previous CFG is not LL(1) No ambiguous grammar is LL(1) 03-27: LL(1) Parser Example S S$ S if E then S else S egin L end S print(e) L ɛ L SL L ; SL L ɛ E num = num 03-28: LL(1) Parser Example Non-Terminal First Follow S if, begin, print S if, begin, print $, end, ; L ɛ, if, begin, print end L ɛ, ; end E num ) 03-29: LL(1) Parser Example if then else begin end print S S S$ S S$ S S$ S S if E then S else S egin L end S print(e) L L SL S S$ L ɛ S S$ L E ( ) ; num = S S L L L ; SL E 03-30: LL(1) Parser Example S S$ S ABC A a A ɛ B b A ɛ C c C ɛ 03-31: Creating an LL(1) CFG E num = num Not all grammars are LL(1) We can often modify a CFG that is not LL(1) New CFG generates the same language as the old CFG New CFG is LL(1) 03-32: Creating an LL(1) CFG Remove Ambiguity

CS414-20034-03 Parsing 7 No ambiguous grammar is LL(1) Grammar is ambiguous if there are two ways to generate the same string If there are two ways to generate a string α, modify the CFG so that one of the ways to generate the string is removed 03-33: Removing Ambiguity Often a grammar is ambiguous when there is a special case rule that can be generated by a general rule Solution: Remove the special case, let the general case handle it S V = E; S V = identifier; E V E integer literal V identifier Structured variable definitions commonly have this problem 03-34: Removing Ambiguity This grammar, for describing variable accesses, is also ambiguous Ambiguous in the same was as expression CFG Can be made unambiguous in a similar fashion V V. V V identifier 03-35: Removing Ambiguity Some Languages are inherently ambiguous A Language L is ambiguous if: For each CFG G that generates L, G is ambiguous No programming languages are inherently ambiguous 03-36: Left Recursion S Sα S β Any CFG that contains these rules (where α and β are any string of terminals and non-terminals) is not LL(1) Why? 03-37: Left Recursion S Sa What should ParseS() do on a b? 03-38: Left Recursion S Sa First Follow S b a

CS414-20034-03 Parsing 8 a b S S Sa 03-39: Left Recursion S Sa What strings can be derived from this grammar? 03-40: Left Recursion S Sa What strings can be derived from this grammar? S b S Sa ba S Sa Saa baa S Sa Saa Saaa baaa S Sa Saa Saaa Saaaa baaaa 03-41: Removing Left Recursion S Sa What strings can be derived from this grammar? A b, followed by zero or more a s. What is a CFG for this language that does not use Left Recursion? 03-42: Removing Left Recursion S Sa What strings can be derived from this grammar? A b, followed by zero or more a s. What is a CFG for this language that does not use Left Recursion? S S as S ɛ 03-43: Removing Left Recursion S Sa What strings can be derived from this grammar? A b, followed by zero or more a s. What is an EBNF for this language that does not use Left Recursion? 03-44: Removing Left Recursion S Sa

CS414-20034-03 Parsing 9 What strings can be derived from this grammar? A b, followed by zero or more a s. What is an EBNF for this language that does not use Left Recursion? (a)* 03-45: Removing Left Recursion In General, if you have rules of the form: S Sα S β You can replace them with the CFG rules S βs S αs S ɛ or the EBNF rules S β(α) 03-46: Removing Left Recursion What about: S Sα 1 S Sα 2 S β 1 S β 2 03-47: Removing Left Recursion What about: S Sα 1 S Sα 2 S β 1 S β 2 S BA B β 1 B β 2 A α 1 A A α 2 A A ɛ We can use the same method for arbitrarily complex grammars 03-48: Left Factoring Consider Fortran DO statements: Fortran: do var = intial, final loop body end do

CS414-20034-03 Parsing 10 Java Equivalent: for (var=initial; var <= final; var++) loop body 03-49: Left Factoring Consider Fortran DO statements: Fortran: do var = intial, final, inc loop body end do Java Equivalent: for (var=initial; var <= final; var+=inc) loop body 03-50: Left Factoring CFG for Fortran DO statements: S do L S L id = exp, exp L id = exp, exp, exp Is this Grammar LL(1)? 03-51: Left Factoring CFG for Fortran DO statements: S do L S L id = exp, exp L id = exp, exp, exp Is this Grammar LL(1)? No! The problem is in the rules for L Two rules for L that start out exactly the same No way to know which rule to apply when looking at just 1 symbol 03-52: Left Factoring Factor out the similar sections from the rules: S do L S L id = exp, exp L id = exp, exp, exp 03-53: Left Factoring

CS414-20034-03 Parsing 11 Factor out the similar sections from the rules: S do L S L id = exp, exp L L, exp L ɛ We can also use EBNF: S do L S L id = exp, exp (, exp)? 03-54: Left Factoring In general, if we have rules of the form: S α β 1 S α β 2... S α β n We can left factor these rules to get: S α B B β 1 B β 2... B β n 03-55: Building an LL(1) Parser Create a CFG for the language Remove ambiguity from the CFG, remove left recursion, and left-factor it Find First/Follow sets for all non-terminals Build the LL(1) parse table Use the parse table to create a suite of mutually recursive functions 03-56: Building an LL(1) Parser Create an EBNF for the language Remove ambiguity from the EBNF, remove left recursion, and left-factor it Find First/Follow sets for all non-terminals Build the LL(1) parse table Use the parse table to create a suite of mutually recursive functions Use a parser generator tool that converts the EBNF into parsing functions 03-57: Structure JavaCC file foo.jj

CS414-20034-03 Parsing 12 options /* Code to set various options flags */ PARSER_BEGIN(foo) public class foo /* This segment is often empty */ PARSER_END(foo) TOKEN_MGR_DECLS : /* Declarations used by lexical analyzer */ /* Token Rules & Actions */ /* JavaCC Rules and Actions -- EBNF for language*/ 03-58: JavaCC Rules JavaCC rules correspond to EBNF rules JavaCC rules have the form: void nonterminalname() : /* Java Declarations */ /* Rule definition */ For now, the Java Declarations section will be empty (we will use it later on, when building parse trees) Non terminals in JavaCC rules are followed by () Terminals in JavaCC rules are between < and > 03-59: JavaCC Rules For example, the CFG rules: S while (E) S S V = E; Would be represented by the JavaCC rule: void statement() : <WHILE> <LPAREN> expression() <RPAREN> statement() variable() <GETS> expression() <SEMICOLON> 03-60: Example JavaCC Files We now examine a JavaCC file that parses prefix expressions Prefix expression examples: Prefix expression Equivalent infix expression + 3 4 3 + 4 + - 2 1 5 (2-1) + 5 + - 3 4 * 5 6 (3-4) + (5 * 6) + - * 3 4 5 6 ((3 * 4) - 5) + 6 + 3-4 * 5 6 3 + (4 - (5 * 6))

CS414-20034-03 Parsing 13 Come up with a CFG for Prefix expressions 03-61: Example JavaCC Files CFG for prefix expressions: E + E E E - E E E * E E E / E E E num Pull up JavaCC file on other screen 03-62: Example JavaCC Files We could also have use the rules for expression: void expression(): <PLUS> expression() expression() <MINUS> expression() expression() <TIMES> expression() expression() <DIVIDE> expression() expression() <INTEGER_LITERAL> Put up driver file, do some examples 03-63: Lookahead Consider the following JavaCC fragment: void S(): "a" "b" "c" "a" "d" "c" Is this grammar LL(1)? 03-64: Lookahead A LOOKAHEAD directive, placed at a choice point, will allow JavaCC to use a lookahead 1: void S(): LOOKAHEAD(2) "a" "b" "c" "a" "d" "c" ParseS will look at the next two symbols, before deciding which rule for S to use 03-65: Lookahead

CS414-20034-03 Parsing 14 LOOKAHEAD directives are placed at choice points places in the grammar where there is more than one possible rule that can match. void S(): "A" (("B" "C") ("B" "D")) 03-66: Lookahead LOOKAHEAD directives are placed at choice points places in the grammar where there is more than one possible rule that can match. void S(): "A" ( LOOKAHEAD(2) ("B" "C") ("B" "D")) 03-67: Lookahead LOOKAHEAD directives are placed at choice points places in the grammar where there is more than one possible rule that can match. void S(): "A" (("B" "C") ("B" "D")) 03-68: Lookahead LOOKAHEAD directives are placed at choice points places in the grammar where there is more than one possible rule that can match. void S(): LOOKAHEAD(2) "A" (("B" "C") ("B" "D")) This is not a valid use of lookahead the grammar will not be parsed correctly. Why not? 03-69: JavaCC & Non-LL(k) JavaCC will produce a parser for grammars that are not LL(1) (and even for grammars that are not LL(k), for any k) The parser that is produced is not guaranteed to correctly parse the language described by the grammar A warning will be issued when JavaCC is run on a non-ll(1) grammar 03-70: JavaCC & Non-LL(k)

CS414-20034-03 Parsing 15 What does JavaCC do for a non-ll(1) grammar? The rule that appears first will be used void S() : "a" "b" "c" "a" "b" "d" 03-71: JavaCC & Non-LL(k) Infamous dangling else void statement(): <IF> expression() <THEN> statement() <IF> expression() <THEN> statement() <ELSE> statement() /* Other statement definitions */ Why doesn t this grammar work? 03-72: JavaCC & Non-LL(k) void statement() : <IF> expression() <THEN> statement() optionalelse() /* Other statement definitions */ void optionalelse() : <ELSE> statement() /* nothing */ if <e> then <S> if <e> then <S> else <S> if <e> then if <e> then <S> else <S> 03-73: JavaCC & Non-LL(k) void statement() : <IF> expression() <THEN> statement() optionalelse() /* Other statement definitions */ void optionalelse() : /* nothing */ <ELSE> statement() What about this grammar? 03-74: JavaCC & Non-LL(k) void statement() : <IF> expression() <THEN> statement() optionalelse() /* Other statement definitions */ void optionalelse() : /* nothing */ <ELSE> statement()

CS414-20034-03 Parsing 16 What about this grammar? Doesn t work! (why?) 03-75: JavaCC & Non-LL(k) void statement() : <IF> expression() <THEN> statement() (<ELSE> statement)? /* Other statement definitions */ This grammar will also work correctly Also produces a warning 03-76: JavaCC & Non-LL(k) void statement() : <IF> expression() <THEN> statement() (LOOKAHEAD(1) <ELSE> statement)? /* Other statement definitions */ This grammar also works correctly Produces no warnings (not because it is any more safe if you include a LOOKAHEAD directive, the system assumes you know what you are doing) 03-77: Parsing Project For your next project, you will write a parser for simplejava using JavaCC. Provided Files: ParseTest.java A main program to test your parser test1.sjave test9.sjava Various simplejava programs to test your parser. Some have parsing errors, some do not. Be sure to test your parser on other test cases, too! These files are not meant to be exhaustive!! 03-78: Parsing Project Gotcha s Expressions can be tricky. Read the text for more examples and suggestions Structured variable accesses are similar to expressions, and have some of the same issues Avoid specific cases that can be handled by a more general case 03-79: Parsing Project Gotcha s Procedure calls and assignment statements can be tricky for LL(1) parsers. You may need to left-factor, and/or use LOOKAHEAD directives LOOKAHEAD directives are useful, but can be dangerous (for instance, you will not get warnings for the sections that use LOOKAHEAD.) Try left-factoring, or other techniques, before resorting to LOOKAHEAD. This project is much more difficult than the lexical analyzer. Start Early!