CECS444 Project #2: LL Parser solution


Original Work


Rate this product

The objective of this assignment is to write a backtracking-free LL Predictive Parser. This parser will make
use of output from the Lexer constructed in the previous project to obtain the token stream of the program being
compiled. (Note, this also allows hand-built lexer-format files to be input by the Parser.)
The Simple LL Predictive Parser consists of three parts: the simple parser machine, the LL parse table for
the grammar involved, and the prediction stack. The simple version of the parser machine is a very short piece
of code because it is table-driven.
During parsing, the LL Parser creates a Parse Tree (PST) of Node objects. Each Node contains (wraps) the
symbol (terminal or non-terminal) it was built for. Each node containing a symbol is built as the RHS of a
selected rule is pushed onto the prediction stack. Once the PST is complete, the Parser outputs the tree as text in
a simple serialized tree format. Finally, the Parser converts the PST to an AST. This AST is then output using
the same serialized tree format.
The team may contain from two to four members. Pick a three-letter name for the team. (If two teams pick
the same TLA, I will disambiguate them.)
Optionally, for teams, establish tasks and each day briefly discuss the Agile 3Qs: 1) What was completed
yesterday?, 2) What is planned to complete today?, and 3) What obstacles are in the way?. Bread up a task so
that some part can be completed each day. If you expect to have down days (i.e., no-work days), tell your team
up front.
LL Parse table
The LL parse table is straight-forward to build (by hand) once the grammar has been converted to simple
LL-compatible form. This involves several preparatory steps with the grammar:
1. Convert the grammar rules to simple rules because only simple rules go in table cells
2. LRE (Left Recursion Elimination), to avoid LL infinite recursion
3. Disappearing Non-Terminal analysis to add direct epsilon rules for ghostable Non-Ts
4. First Set construction, to see which simple rules go into which LL table cells
5. Fill the LL Table cells
6. If there are cell conflicts, use Left Factoring to avoid more than one simple rule in a cell
7. Follow Set construction, to see which epsilon rules go into which LL table cells
8. ID which RHS symbol will “own” the rest in the AST (or leave the mom Non-T as the owner)
This will typically leave a number of cells unfilled. If the LL Parser machine looks up one of these empty
cells, the Parser (step M3E) emits an error and stops. The error should indicate the token (i.e., column header)
and the top-of-stack symbol (i.e., the rule LHS) and the token’s line number (if known).
 Match a prediction stack node’s symbol against an input stream’s token; via token kind.
 Build a node for a symbol; several nodes can be built for the same symbol.
 Mom node should know the rule used to build its kids; and have easy access to them for treewalking
 Table cell should have access to its rule
 Rule should have easy access to its RHS symbols
 Leaf node should know the token it was built for; for 1) variable name and 2) error line # info
 Should be easy to tell if a node’s symbol is a terminal or a non-terminal
 Need an “input stream” easy to use (e.g., read each text-token into an array of Token refs)
C. Siska October 11, 2018 Page 1 of 3
444 Compilers — Project #2 — Parser
 How to do Rule #2 Add-a-Trick for a parser, because of the massive bug hunt potential for all of this.
Tree Serialization
Tree Serialization is done via a treewalk in pre-order (mom before kids).
Each node in a tree is serialized as follows (with a space between each part).
1. Output a ‘(‘ parenthesis, and “Node:”
2. Output the node’s local field information (see below for this)
3. Output each child node, recursively, if any
4. Output a ‘)’ parenthesis – do this using a post-order lollypop
An object’s local information should look like the following:
1. Output a ‘(‘ parenthesis
2. Output the object’s class or data type name (e.g., “Rule:” )
3. Output the object’s ID number
Note: Each object should get a unique ID number on creation (eg, counter, or memory location)
For a given object type, these ID numbers don’t have to be sequential, just unique.
4. For each local field, output a tuple of the field name, “=”, the field value, and “;”
If the value is a pointer (or reference), then output that object’s class name and unique ID
5. Output a ‘)’ parenthesis
Indentation, line wrapping, etc. are all optional. The easiest solution is to output a newline before every ‘(‘
A6 Grammar
For this project we will use the A6 grammar, specified in the Appendix.
1. In a pdf document, show any new epsilon rules; show each LHS rules before and after for LRE; show
before and after for any Left Factored rules, show the First Set for each rule, show the Follow Set
for each LHS non-terminal symbol, and for each non-trivial rule show the RHS owner node to be
hoisted (or indicate the LHS will be kept in place because no RHS seemed appropriate).
2. A6-table: The A6 LL Parser table as a spreadsheet or an importable text CSV file.
3. LL-Parser: The LL Parser machine’s source code, which you used to test the parser table on the example
A6 programs from the Lexer project.
4. Readme: the README.txt file (e.g., title, contact info, files list, installation/run info, bugs remaining,
features added, citations of work referred to).
5. Five output runs of your parser, one for each of the 3 Lexer’s sample programs, and two of your own
choosing. Two outputs for each: one for the PST and one for the AST. Note, if you like, you can use
hand-built input to your Parser, or you can use someone else’s Lexer output as input (but cite it).
Academic Rules
Correctly and properly attribute all third party material and references, if you used any.
Submission & Grading
Same as for project #1.
C. Siska October 11, 2018 Page 2 of 3
444 Compilers — Project #2 — Parser
Appendix — A6 Grammar
Pgm = kwdprog Vargroup Fcndefs Main
Main = kwdmain BBlock
BBlock = brace1 Vargroup Stmts brace2
Vargroup = kwdvars PPvarlist | eps
PPvarlist = parens1 Varlist parens2
Varlist = Varitem semi Varlist | eps
Varitem = Vardecl | Vardecl equal Varinit
Varitem = Classdecl | Classdef
Vardecl = Simplekind Varspec
Simplekind = Basekind | Classid
Basekind = int | float | string
Classid = id
Varspec = Varid | Arrspec | Deref_id
Varid = id
Arrspec = Varid KKint
KKint = bracket1 int bracket2
Deref_id = Deref id
Deref = aster
Varinit = Expr | BBexprs
BBexprs = brace1 Exprlist brace2 | brace1 brace2
Exprlist = Expr Moreexprs
Moreexprs = comma Exprlist | eps
Classdecl = kwdclass Classid
Classdef = Classheader BBclassitems
BBClassitems = brace1 Classitems brace2
Classheader = Classdecl Classmom Interfaces
Classmom = colon Classid | eps
Classitems = Classgroup Classitems | eps
Classgroup = Class_ctrl | Varlist | Mddecls
Class_ctrl = colon id // in {public, protected, private}
Interfaces = colon Classid Interfaces | eps
Mddecls = Mdheader Mddecls | eps
Mdheader = kwdfcn Md_id PParmlist Retkind
Md_id = Classid colon Fcnid
Fcndefs = Fcndef Fcndefs | eps
Fcndef = Fcnheader BBlock
Fcnheader = kwdfcn Fcnid PParmlist Retkind
Fcnid = id
Retkind = Kind
PParmlist = parens1 Varspecs parens2 | PPonly
Varspecs = Varspec More_varspecs
More_varspecs = comma Varspecs | eps
PPonly = parens1 parens2
Stmts = Stmt semi Stmts | eps
Stmt = Stasgn | Fcall | Stif
Stmt = Stwhile | Stprint | Strtn
Stasgn = Lval equal Expr
Lval = Varid | Aref | Deref_id
Aref = Varid KKexpr
KKexpr = bracket1 Expr bracket2
Fcall = Fcnid PPexprs
PPexprs = parens1 Exprlist parens2 | PPonly
Stif = kwdif PPexpr BBlock Elsepart
Elsepart = kwdelseif PPexpr BBlock Elsepart
Elsepart = kwdelse BBlock | eps
Stwhile = kwdwhile PPexpr BBlock
Stprint = kprint PPexprs
Strtn = kwdreturn Expr | kwdreturn
PPexpr = parens1 Expr parens2
Expr = Expr Oprel Rterm | Rterm
Rterm = Rterm Opadd Term | Term
Term = Term Opmul Fact | Fact
Fact = Basekind | Lval | Addrof_id | Fcall | PPexpr
Addrof_id = ampersand id
Oprel = opeq | opne | Lthan | ople | opge | Gthan
Lthan = angle1
Gthan = angle2
Opadd = plus | minus
Opmul = aster | slash | caret
C. Siska October 11, 2018 Page 3 of 3