/// <summary> /// Type ::= ("int" | Identifier) [ "[" "]" ] . /// </summary> /// <returns></returns> private TYPE parseType() { TYPE result = new TYPE(); Token token = lexer.get(); if ( token.code == TokenCode.INT ) { result.classRef = null; result.isArray = false; result.className = token.image; lexer.forget(); } else if ( token.code == TokenCode.IDENTIFIER ) { result.className = token.image; lexer.forget(); } else errors.issue(token,13); // type expected token = lexer.get(); if ( token.code == TokenCode.LBRACKET ) { lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.RBRACKET ) errors.issue(token,11,"]"); else lexer.forget(); result.isArray = true; } return result; }
/// <summary> /// Body ::= "{" {LocalDeclaration} {Statement} "}". /// /// Statement ::= Assignment /// | IfStatement /// | WhileStatement /// | ReturnStatement /// | CallStatement /// | PrintStatement /// | Block /// </summary> /// <returns></returns> private ENTITY parseBodyElement() { Token token = lexer.get(); switch ( token.code ) { case TokenCode.IF : { // IfStatement ::= "if" "(" Relation ")" Statement ["else" Statement]. IF ifStmt = new IF(); lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.LPAREN ) lexer.skipUntil(TokenCode.RPAREN); else { lexer.forget(); ifStmt.relation = parseRelation(); } token = lexer.get(); if ( token.code == TokenCode.RPAREN ) lexer.forget(); else lexer.skipUntil(TokenCode.RPAREN); ifStmt.thenPart = parseBodyElement() as STATEMENT; token = lexer.get(); if ( token.code == TokenCode.ELSE ) { lexer.forget(); ifStmt.elsePart = parseBodyElement() as STATEMENT; } return ifStmt; } case TokenCode.WHILE: { // WhileStatement ::= "while" "(" Relation ")" Statement . WHILE whileStmt = new WHILE(); lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.LPAREN ) { errors.issue(token,20); lexer.skipUntil(TokenCode.RPAREN); } else { lexer.forget(); whileStmt.relation = parseRelation(); } token = lexer.get(); if ( token.code == TokenCode.RPAREN ) lexer.forget(); else lexer.skipUntil(TokenCode.RPAREN); whileStmt.body = parseBodyElement() as STATEMENT; return whileStmt; } case TokenCode.RETURN: { // ReturnStatement ::= "return" [Expression] ";" RETURN returnStmt = new RETURN(); lexer.forget(); token = lexer.get(); if ( token.code == TokenCode.SEMICOLON ) lexer.forget(); else { returnStmt.result = parseExpression(); token = lexer.get(); if ( token.code != TokenCode.SEMICOLON ) lexer.skipUntil(TokenCode.SEMICOLON); lexer.forget(); } return returnStmt; } case TokenCode.PRINT: { // PrintStatement ::= "print" "(" Expression ")" ";". PRINT print = new PRINT(); lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.LPAREN ) goto Error; lexer.forget(); print.value = parseExpression(); token = lexer.get(); if ( token.code != TokenCode.RPAREN ) goto Error; lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.SEMICOLON ) goto Error; lexer.forget(); return print; Error: errors.issue(token,19); lexer.skipUntil(TokenCode.SEMICOLON); lexer.forget(); return null; } case TokenCode.LBRACE: { // Block ::= "{" {Statement} "}". lexer.forget(); BLOCK block = new BLOCK(); while ( true ) { STATEMENT statement = parseBodyElement() as STATEMENT; if ( statement == null ) break; block.statements.Add(statement); } token = lexer.get(); if ( token.code != TokenCode.RBRACE ) lexer.skipUntil(TokenCode.RBRACE); lexer.forget(); return block; } case TokenCode.INT: { // int x; // int[] x; bool isArray = false; lexer.forget(); token = lexer.get(); if ( token.code == TokenCode.LBRACKET ) { isArray = true; lexer.forget(); token = lexer.get(); if ( token.code != TokenCode.RBRACKET ) { errors.issue(token,17); lexer.skipUntil(TokenCode.SEMICOLON); return null; } else lexer.forget(); } string fname = ""; token = lexer.get(); if ( token.code != TokenCode.IDENTIFIER ) { errors.issue(token,17); lexer.skipUntil(TokenCode.SEMICOLON); return null; } else { fname = token.image; lexer.forget(); } token = lexer.get(); if ( token.code != TokenCode.SEMICOLON ) lexer.skipUntil(TokenCode.SEMICOLON); lexer.forget(); TYPE type = new TYPE(); type.classRef = null; type.className = "int"; type.isArray = isArray; FIELD local = new FIELD(0,fname); local.type = type; local.isLocal = true; return local; } case TokenCode.IDENTIFIER: { // Assignment ::= Identifier ["." Identifier | "[" Expression "]" ] "=" Expression ";" // // CallStatement ::= Identifier ["." Identifier] "(" [Expression {"," Expression}]")" ";". // // LocalDeclaration ::= Type Identifier ";". ENTITY result = null; NAME name = parseName(); if ( name == null ) // An error was detected { lexer.skipUntil(TokenCode.SEMICOLON); return null; } // After that goes either assignment of left parenthesis. token = lexer.get(); if ( token.code == TokenCode.ASSIGN ) { lexer.forget(); EXPRESSION rightSide = parseExpression(); ASSIGNMENT assignment = new ASSIGNMENT(); assignment.name = name; assignment.expression = rightSide; result = assignment; } else if ( token.code == TokenCode.LPAREN ) { lexer.forget(); CALL call = new CALL(); call.name = name; while ( true ) { token = lexer.get(); if ( token.code == TokenCode.RPAREN ) { lexer.forget(); break; } call.arguments.Add(parseExpression()); token = lexer.get(); if ( token.code == TokenCode.COMMA ) { lexer.forget(); continue; } else if ( token.code != TokenCode.RPAREN ) { errors.issue(token,18); lexer.skipUntil(TokenCode.SEMICOLON); return null; } } result = call; } else if ( token.code == TokenCode.IDENTIFIER ) { // Dont't forget() // A local declaration? // -- Converting NAME to TYPE TYPE type = new TYPE(); type.className = name.name; type.isArray = name is ARRAY_ELEM; FIELD local = new FIELD(0,token.image); local.type = type; result = local; lexer.forget(); } token = lexer.get(); if ( token.code != TokenCode.SEMICOLON ) { errors.issue(token,19); lexer.skipUntil(TokenCode.SEMICOLON); } lexer.forget(); return result; } case TokenCode.RBRACE : // End of method body // Don't forget(). return null; default : errors.issue(token,17); lexer.skipUntil(TokenCode.SEMICOLON); lexer.forget(); return null; } }