QUESTIONS LAST TIME: - Refactoring, interfaces, DeathBox spec.. TODAY: - Your SiteRiter questions - Re|new java: enum - Grammars and parsing HOMEWORK - QUIZ COMING on Java operators!,~,+,-,*,/,^,&,|,++,--,&&,||,<<,>>,<<< etc! PROJECT 1 STATUS DAY 2: +---------------+ - Interim deliverable #1 DUE Wed Sep 4, 2013 12NOON MST |0 DAYS 23 HOURS| +---------------+ A USEFUL PAIN LANGUAGE LAWYER n. A person, usually an experienced or senior software engineer, who is intimately familiar with many or most of the numerous restrictions and features (both useful and esoteric) applicable to one or more computer programming languages. A language lawyer is distinguished by the ability to show you the five sentences scattered through a 200-plus-page manual that together imply the answer to your question "if only you had thought to look there". Compare wizard, legal, legalese. PROJECT 1 QUESTIONS PROJECT 1 DELIVERABLE 1 RUBRIC ELEMENTS Overall dimensions: CORRECTNESS 5 pts Are the tests correct wrt spec? COVERAGE 7 pts Is the interface thoroughly tested? CLARITY 3 pts Is the code clean? Readable? Refactored? PROJECT 1 TIMELINE ((T.2)) Project timeline ((T.2.1)) When: Wed Aug 28, 2013 What: Project released +-----------------------------------------------------------------------+ |((T.2.2)) INTERIM DELIVERABLE#1 DEADLINE [START+7 DAYS] | |When: Wed Sep 4, 2013 12NOON MST | |What: Last possible ON-TIME code turn-in of: | | Compilable, runnable JUnit tests for the interface | | com.putable.siteriter.SDLParser (but no _actual_ implementation | | is required). Must include _numerous_ tests beyond the examples | | given in the spec. setup() (and/or tests) should presume the | | existence of an com.putable.siteriter.test.SDLParserImpl class | | that implements SDLParser, and make and test instances of | | that class. | +-----------------------------------------------------------------------+ ((T.2.3)) When: Sat Sep 7, 2013 11:59:59AM MST What: Last possible LATE turn-in of INTERIM DELIVERABLE#1 (T.2.2) for any credit must occur BEFORE NOON SAT SEP 7, 2013 PROJECT 1 TIMELINE ((T.2)) Project timeline ((T.2.1)) When: Wed Aug 28, 2013 What: Project released +-----------------------------------------------------------------------+ |((T.2.2)) INTERIM DELIVERABLE#1 DEADLINE [START+7 DAYS] | |When: Wed Sep 4, 2013 12NOON MST | |What: Last possible ON-TIME code turn-in of: | | Compilable, runnable JUnit tests for the interface | | com.putable.siteriter.SDLParser (but no _actual_ implementation | | is required). Must include _numerous_ tests beyond the examples | | given in the sp+----------------------------------------+ the | | existence of an|com.putable.siteriter.test.SDLParserImpl|class | | that implements+----------------------------------------+ | | that class. | +-----------------------------------------------------------------------+ ((T.2.3)) When: Sat Sep 7, 2013 11:59:59AM MST What: Last possible LATE turn-in of INTERIM DELIVERABLE#1 (T.2.2) for any credit must occur BEFORE NOON SAT SEP 7, 2013 PROJECT 1 TIMELINE ((T.2)) Project timeline ((T.2.1)) When: Wed Aug 28, 2013 What: Project released +-----------------------------------------------------------------------+ |((T.2.2)) INTERIM DELIVERABLE#1 DEADLINE [START+7 DAYS] | |When: Wed Sep 4, 2013 12NOON MST | |What: Last possible ON-TIME code turn-in of: | | Compilable, runnable JUnit tests for the interface | | com.putable.siteriter.SDLParser (but no _actual_ implementation | | is required). Must include _numerous_ tests beyond the examples | | given in the spec. setup() (and/or tests) should presume the | | existence of an com.putable.siteriter.test.SDLParserImpl class | | that implements SDLParser, and make and test instances of | | that class. | +-----------------------------------------------------------------------+ ((T.2.3)) When: Sat Sep 7, 2013 11:59:59AM MST What: Last possible LATE turn-in of INTERIM DELIVERABLE#1 (T.2.2) for any credit must occur BEFORE NOON SAT SEP 7, 2013 REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE AFTER +-----------------------+ |HelloWorld (interface) | +--------------+ +-------------------+ |\ |-----------------------| |HelloWorld | |AbstractHelloWorld |...| >| | |--------------| |-------------------| |/ |-----------------------| | | | | |void run() ; | |--------------| |-------------------| | | |void run() | |void run() { .. } | +-----------------------+ |void main(..) | | | +--------------+ +-------------------+ ^ - This is all such a win / \ why, again? --- | +-------------------+ |ConcreteHelloWorld | |-------------------| | | |-------------------| |void main(..) | | | +-------------------+ RE|NEW JAVA: STATIC/INSTANCE STATE: UPSHOTS - 'static' stuff is associated with the class itself = static fields 'live in the class' and (thus) are shared by instances = static methods can be used without having access to an instance - non-static stuff is associated with instances of a class = non-static fields 'live in the instance' = non-static methods can only be called when an instance is accessible - static, class-level stuff is initialized when a class is loaded (actually, really just before it's needed, I think..) - object instances are created using 'new'. (There's one other way, but..) = non-static fields are initialized during the creation of an instance - Capitalization counts = ClassNames are leading capital, mixed caps = methodNames and non-final fieldNames are leading lowercase, mixed caps = final FIELD_NAMES are all caps, _ word-separated RE|NEW JAVA: INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } - Interfaces can contain method signatures and field declarations = All interface method declarations are automatically public = All interface field declarations are automatically public static final - So they must be initialized.. = Can include or omit the 'public's and 'public static final's in interface declarations. Maybe more pro to omit. = Interface field declarations are slightly on the bogus side.. public interface Foo { int woof(); String clank="honk?"; } RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); } } * RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(v); } } * RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(v==MetaVar.BAR); } } * RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(v==MetaVar.BAR); // Don't need v.equals(MetaVar.BAR)! } } * RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "[FOO, BLETCH]"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(v); } } * RE|NEW JAVA: ENUM enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(MetaVar.BLETCH.ordinal()); } } * RE|NEW JAVA: ENUM import java.util.EnumSet; enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(MetaVar.BLETCH.ordinal()); EnumSet set = EnumSet.of(MetaVar.BLETCH); set.add(MetaVar.FOO); System.out.println(set); } } * RE|NEW JAVA: ENUM import java.util.EnumSet; enum MetaVar { FOO, BAR, BLETCH }; public class Test { public static void main(String[] args) { System.out.println(MetaVar.FOO); String s = "BAR"; MetaVar v = Enum.valueOf(MetaVar.class,s); System.out.println(MetaVar.BLETCH.ordinal()); EnumSet set = EnumSet.of(MetaVar.BLETCH); set.add(MetaVar.FOO); System.out.println(set); } } - Generics.. * RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.LOWER; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } * RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.LOWER; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } * RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } -> Prints: Java Ugh! RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } * RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN; }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } * RE|NEW JAVA: ENUM enum TextOp { UPPER, LOWER, PIGLATIN; public abstract String fix(String in); }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } RE|NEW JAVA: ENUM enum TextOp { UPPER { public String fix(String s) { return s.toUpperCase(); } }, LOWER { public String fix(String s) { return s.toLowerCase(); } }, PIGLATIN; public abstract String fix(String in); }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } RE|NEW JAVA: ENUM enum TextOp { UPPER { public String fix(String s) { return s.toUpperCase(); } }, LOWER { public String fix(String s) { return s.toLowerCase(); } }, PIGLATIN { public String fix(String s) { ?? } }; public abstract String fix(String in); }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; // .. switch (top) { case UPPER: s = s.toUpperCase(); break; case LOWER: s = s.toLowerCase(); break; } System.out.println(s); } } RE|NEW JAVA: ENUM enum TextOp { UPPER { public String fix(String s) { return s.toUpperCase(); } }, LOWER { public String fix(String s) { return s.toLowerCase(); } }, PIGLATIN { public String fix(String s) { ?? } }; public abstract String fix(String in); }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; System.out.println(top.fix(s)); } } RE|NEW JAVA: ENUM enum TextOp { UPPER { public String fix(String s) { return s.toUpperCase(); } }, LOWER { public String fix(String s) { return s.toLowerCase(); } }, PIGLATIN { public String fix(String s) { return s.replaceFirst("^(.*?)([aeiouAEIOU].*)$","$2$1ay"); } }; public abstract String fix(String in); }; public class Test { public static void main(String[] args) { String s = "Java"; TextOp top = TextOp.PIGLATIN; System.out.println(top.fix(s)); } } * RE|NEW JAVA: ENUM - Represent set of 'constants' - Can compare with == instead of .equals - Can use as case targets in switch statements. (But think twice on design.) - Can iterate cleanly over the set using EnumSet - Can add constant-specific behavior (often reducing need for switch stmts.) - WARNING! Avoid mutable state in enums! GRAMMARS AND PARSING GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 1 Rule: FOO <- "drink" Start symbol == FOO GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 1 Rule: FOO <- "drink" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm chug alug FOO | drink GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 1 Rule: FOO <- "drink" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm chug alug FOO | (legal) (no) (no) drink (no) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 2 Rule: FOO <- "drink" | "slurm" Start symbol == FOO GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 2 Rule: FOO <- "drink" | "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | drink GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 2 Rule: FOO <- "drink" | "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | (legal) (legal) (no) drink (no) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 3 Rule: FOO <- "drink" + "slurm" Start symbol == FOO GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 3 Rule: FOO <- "drink" + "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | drink GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 3 Rule: FOO <- "drink" + "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | (no) (no) (legal) drink (no) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 4 Rule: FOO <- "drink" + BAR BAR <- "slurm" Start symbol == FOO GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 4 Rule: FOO <- "drink" + BAR BAR <- "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | drink GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 4 Rule: FOO <- "drink" + BAR BAR <- "slurm" Start symbol == FOO FOO FOO FOO FOO | | / \ | drink slurm drink slurm FOO | (no) (no) (no) drink (no) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 4 ZOT := [ "gah" ] Rule: ZOT <- | "gah" FOO <- "drink" + BAR BAR <- "slurm" Start symbol == FOO FOO FOO FOO FOO FOO | | / \ | / \ drink slurm drink slurm FOO drink BAR | | (no) (no) (no) drink slurm (no) (legal) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO FOO FOO FOO FOO FOO | | / \ | / \ drink slurm drink slurm FOO drink BAR | | (no) (no) (no) drink slurm (no) (legal) GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO drink drink drink slurm GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO FOO drink drink drink slurm GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO FOO--\ | BAR | | | | | | | drink drink drink slurm GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO FOO--\ | BAR | | | FOO | | | | | drink drink drink slurm GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin Example 5 Rule: FOO <- "drink" + BAR BAR <- "slurm" | FOO Start symbol == FOO FOO--\ | BAR | | | FOO--\ | | BAR | | | | | FOO--\ | | | BAR | | | | drink drink drink slurm GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin - Grammar rules consist of TERMINAL symbols (like "drink" and "slurm") and NON-TERMINAL symbols (like FOO and BAR) - Terminal symbols appear only as leaves in legal inputs; non-terminal symbols only as interior nodes in legal inputs GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin - Grammar rules consist of TERMINAL symbols (like "drink" and "slurm") and NON-TERMINAL symbols (like FOO and BAR) - Terminal symbols appear only as leaves in legal inputs; non-terminal symbols only as interior nodes in legal inputs - Grammar rules can use '|' to express 'either or'. - Grammar rules can use '+' to represent 'and then'. GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin - Grammar rules consist of TERMINAL symbols (like "drink" and "slurm") and NON-TERMINAL symbols (like FOO and BAR) - Terminal symbols appear only as leaves in legal inputs; non-terminal symbols only as interior nodes in legal inputs - Grammar rules can use '|' to express 'either or'. - Grammar rules can use '+' to represent 'and then'. - Grammar rules can be recursive GRAMMARS AND PARSING - A grammar is a way of describing a set of strings in a language - A grammar consists of a set of RULES describing how legal inputs can be put together, and a START SYMBOL saying where to begin - Grammar rules consist of TERMINAL symbols (like "drink" and "slurm") and NON-TERMINAL symbols (like FOO and BAR) - Terminal symbols appear only as leaves in legal inputs; non-terminal symbols only as interior nodes in legal inputs - Grammar rules can use '|' to express 'either or'. - Grammar rules can use '+' to represent 'and then'. - Grammar rules can be recursive - Lots of different ways that grammars are written. Just figure out what counts as terminal, what counts as non-terminal, what counts as sequence and alternation, and what counts as the start symbol, and then the surface notation doesn't matter TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM | 9 TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM | 9 no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E if (a || c && v) NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E | | 9 NUM | 3 no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E | | 9 NUM | 3 no yes TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E | | | 9 NUM NUM | | 3 123 no yes TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E | | | 9 NUM NUM | | 3 123 no yes no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E | | | /|\ 9 NUM NUM NUM + NUM | | | | 3 123 7 7 no yes no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E | | | /|\ 9 NUM NUM NUM + NUM | | | | 3 123 7 7 no yes no no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E E | | | /|\ /|\ 9 NUM NUM NUM + NUM NUM + E | | | | | | 3 123 7 7 7 NUM | 7 no yes no no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E E | | | /|\ /|\ 9 NUM NUM NUM + NUM NUM + E | | | | | | 3 123 7 7 7 NUM | 7 no yes no no yes TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E E E | | | /|\ /|\ /|\ 9 NUM NUM NUM + NUM NUM + E E + NUM | | | | | | | | 3 123 7 7 7 NUM NUM 7 | | 7 7 no yes no no yes TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E E E | | | /|\ /|\ /|\ 9 NUM NUM NUM + NUM NUM + E E + NUM | | | | | | | | 3 123 7 7 7 NUM NUM 7 | | 7 7 no yes no no yes no TREES - more grammars Example 6 Rule: E <- NUM | NUM + "+" + E NUM <- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" Start symbol == E NUM E E E E E | | | /|\ /|\ /|\ 9 NUM NUM NUM + NUM NUM + E E + NUM | | | | | | | | 3 123 7 7 7 NUM NUM 7 | | 7 7 no yes no no yes no ..OK, but how do you write CODE to do this??..