![]() |
![]() |
|
home—info—lectures—exams—hws—archive
Outline: - demo hw sol'ns; discuss a bit. (Final effort due Wed.) - mutual recursive data def'n: - descendent trees - example: S-expressions - example: file structure - grammars and parse trees The book, p. 121, gives a grammar.[if_stmt] ::= if [boolean_expr] then [stmt] [if_stmt] ::= if [boolean_expr] then [stmt] else [stmt]Here we add on a few extra rules, to hint at the fuller picture:[boolean_expr] ::= [AExpr] < [AExpr] [boolean_expr] ::= [AExpr] <= [AExpr] [boolean_expr] ::= [AExpr] == [AExpr] etc. [AExpr] ::= [number] [AExpr] ::= [variable] [AExpr] ::= [AExpr] + [AExpr] [AExpr] ::= [AExpr] - [AExpr] [AExpr] ::= [AExpr] * [AExpr] [AExpr] ::= [AExpr] / [AExpr] [AExpr] ::= ([AExpr])Now let's look at some particular arithmetic expression, "3+4*5". (Note that we're only looking at SYNTAX, not semantics -- we don't care what this means, we only want to know if it should compile as a valid AExpr. We can look at the series of derivations: [AExpr] -> [AExpr] + [AExpr] -> [number] + [AExpr] -> 3 + [AExpr] -> 3 + [AExpr] * [AExpr] -> 3 + [AExpr] * [number] -> 3 + [AExpr] * 5 -> 3 + [number] * 5 -> 3 + 4 * 5 which is the string we wanted to derive. Note the process: Starting from the "nonterminal" AExpr, we apply one of the "production rules" from the grammar that has AExpr on its left-hand-side. We continue, choosing one of our nonterminals, and re-placing it with the right-hand-side of one of its production rules. We stop when we only have terminals (things that don't occur on any left-hand-side of a production). These productions also correspond to a "parse tree": AExpr / | \ AExpr + AExpr | / | \ number AExpr * AExpr | | | 3 number number | | 4 5 This parse tree is *almost* the same information as as the series of productions (technically, the productions impose an ordering that isn't in the tree; however, we won't care about what order the branches are expanded in; that is an issue for advanced parsing algorithms.) Final note: There is one bad thing about this grammar: We can make *two* different parse trees for the same AExpr "3+4*5": AExpr / | \ AExpr * AExpr / | \ | AExpr + AExpr number | | | number number 5 | | 3 4 We say a grammar is ambiguous if some string has two parse trees. Expression trees: (A stripped down version of parse-trees where we don't show the non-terminals, and the root is enough to identify which rule was used:) + * / \ vs / \ 3 * + 5 / \ / \ 4 5 3 4 (We won't use expression trees technically, but stripping away the nonterminals certainly improves readability.) Although we glossed over it, really there are even production rules for number:[number] ::= [digit] [number] ::= [digit][number] [digit] ::= 0 [digit] ::= 1 [digit] ::= 2 [digit] ::= 3 … [digit] ::= 9Didn't get to: - representing parse trees
home—info—lectures—exams—hws—archive
©2009, Ian Barland, Radford University Last modified 2009.Mar.23 (Mon) |
Please mail any suggestions (incl. typos, broken links) to ibarland ![]() |
![]() |