Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CMPE 152: Compiler Design April 6 Class Meeting Department of Computer Engineering San Jose State University Spring 2017 Instructor: Ron Mak www.cs.sjsu.edu/~mak 1 Syntax Error Handling and JavaCC 1. Detect the error. 2. Flag the error. 3. JavaCC does that based on the grammar in the .jj file. JavaCC does that for you with its error messages. Recover from the error so you can continue parsing. You set this up using JavaCC. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 2 Token Errors By default, JavaCC throws an exception whenever it encounters a bad token. Token errors are considered extremely serious and will stop the translation unless you take care to recover from them. Example LOGO program that moves a cursor on a screen: FORWARD 20 RIGHT 120 FORWARD 20 Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 3 Token Errors, cont’d SKIP : { " " | "\n" | "\r" | "\r\n" } logo_tokenizer.jj TOKEN : { <FORWARD : "FORWARD"> | <RIGHT : "RIGHT"> | <DIGITS: (["1"-"9"])+ (["0"-"9"])*> What happens if we feed the tokenizer bad input? FORWARD 20 LEFT 120 FORWARD 20 Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak Demo 4 Token Errors, cont’d One way to recover from a token error is to skip over the erroneous token. public static void main(String[] args) throws Exception { java.io.Reader reader = new java.io.FileReader(args[0]); SimpleCharStream scs = new SimpleCharStream(reader); LogoTokenManager mgr = new LogoTokenManager(scs); while (true) { try { if (readAllTokens(mgr).kind == EOF) break; } catch (TokenMgrError tme) { System.out.println("TokenMgrError: " + tme.getMessage()); skipTo(' '); } } logo_skip_chars.jj } Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 5 Token Errors, cont’d private static void skipTo(char delimiter) throws java.io.IOException { String skipped = ""; char ch; logo_skip_chars.jj System.out.print("*** SKIPPING ... "); while ((ch = input_stream.readChar()) != delimiter) { skipped += ch; } System.out.println("skipped '" + skipped + "'"); } Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak Demo 6 Synchronize the Parser Skipping over a bad token isn’t a complete solution. The parser still needs to synchronize at the next good token and then attempt to continue parsing. SKIP : { logo_synchronize.jj " " First, add an error token to represent any invalid input characters: Computer Engineering Dept. Spring 2017: April 6 } TOKEN : { <FORWARD : "FORWARD"> | <RIGHT : "RIGHT"> | <DIGITS : (["1"-"9"])+ (["0"-"9"])*> | <EOL : "\r" | "\n" | "\r\n"> | <ERROR : ~["\r", "\n"]> } Any character except \r or \n. CMPE 152: Compiler Design © R. Mak 7 Synchronize the Parser, cont’d A program consists of one or more move (FORWARD) and turn (RIGHT) commands. Must also allow for an erroneous command. logo_synchronize.jj void Program() : {} { ( try { MoveForward() {System.out.println("Processed Move FORWARD");} | TurnRight() {System.out.println("Processed Turn RIGHT");} | Error() {handleError(token);} } catch (ParseException ex) { handleError(ex.currentToken); } )+ } Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 8 Synchronize the Parser, cont’d void MoveForward() : {} { <FORWARD> <DIGITS> <EOL> } void TurnRight() : {} { <RIGHT> <DIGITS> <EOL> } void Error() : {} { <ERROR> logo_synchronize.jj } The Error() production rule is invoked for the <ERROR> token. The <ERROR> token consumes the bad character. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 9 Synchronize the Parser, cont’d logo_synchronize.jj JAVACODE String handleError(Token token) { System.out.println("*** ERROR: Line " + token.beginLine + " after \"" + token.image + "\""); Token t; do { t = getNextToken(); } while (t.kind != EOL); return t.image; Synchronize the parser to the next “good” token (EOL). You can do this better with a complete synchronization set! } The JAVACODE header precedes pure Java code that’s inserted into the generated parser. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak Demo 10 Repair the Parse Tree After the parser recovers from an error, you may want to remove a partially-built AST node. The erroneous production must call jjtree.popNode(). logo_tree_recover.jjt JAVACODE String handleError(Token token) #void { System.out.println("*** ERROR: Line " + token.beginLine + " after \"" + token.image + "\""); Token t; do { t = getNextToken(); } while (t.kind != EOL); } jjtree.popNode(); return t.image; Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak Demo 11 Debugging the Parser Add the option to debug the parser. options { DEBUG_PARSER=true; } Print production rule method calls and returns. Print which tokens are consumed. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 12 Review: Interpreter vs. Compiler Same front end Same intermediate tier parser, scanner, tokens symbol tables, parse trees Different back end operations Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 13 Review: Interpreter vs. Compiler, cont’d Interpreter: Use the symbol tables and parse trees to execute the source program. executor Compiler: Use the symbol tables and parse trees to generate an object program for the source program. code generator Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 14 Target Machines A compiler’s back end code generator produces object code for a target machine. Target machine: the Java Virtual Machine (JVM) Object language: the Jasmin assembly language The Jasmin assembler translates the assembly language program into .class files. Java implements the JVM which loads and executes .class files. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 15 Target Machines, cont’d Instead of using javac to compile a source program written in Java into a .class file. Use your compiler to compile a source program written in your chosen language into a Jasmin object program. Then use the Jasmin assembler to create the .class file. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 16 Target Machines, cont’d No matter what language the source program was originally written in, once it’s been compiled into a .class file, Java will be able to load and execute it. The JVM as implemented by Java runs on a wide variety of hardware platforms. Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 17 Java Virtual Machine (JVM) Architecture Java stack Heap area CMPE 152: Compiler Design © R. Mak code for methods constants pool Native method stacks Computer Engineering Dept. Spring 2017: April 6 dynamically allocated objects automatic garbage collection Class area runtime stack support native methods, e.g., written in C (not shown) 18 Java Virtual Machine Architecture, cont’d The runtime stack contains stack frames. Stack frame = activation record. Each stack frame contains local variables array operand stack program counter (PC) What is missing in the JVM that we had in our Pascal interpreter? Computer Engineering Dept. Spring 2017: April 6 CMPE 152: Compiler Design © R. Mak 19