/// <summary> /// Parameter ::= Type Identifier. /// </summary> /// <param name="stop"></param> /// <returns></returns> private FIELD parseParameter() { Token token; // Parameter ::= Type Identifier. FIELD result = null; string name = null; TYPE parType = parseType(); if ( parType == null ) errors.issue(null,15); // incorrect type token = lexer.get(); if ( token.code == TokenCode.IDENTIFIER ) { name = token.image; lexer.forget(); result = new FIELD(0,name); result.type = parType; result.isStatic = false; } else { errors.issue(token,11,"identifier"); lexer.skipUntil(TokenCode.RPAREN); result = new FIELD(0,""); } result.isParameter = true; return result; }
/// <summary> /// FieldDeclaration ::= [Visibility] ["static"] Type Identifier ";". /// /// MethodDeclaration ::= [Visibility] ["static"] ("void" | Type) Identifier /// "("[Parameter {"," Parameter}] ")" Body. /// /// Visibility ::= "private" | "public" | "private". /// /// Parameter ::= Type Identifier. /// /// Body ::= "{" {LocalDeclaration} {Statement} "}". /// /// LocalDeclaration ::= Type Identifier ";". /// </summary> /// <returns></returns> private DECLARATION parseMethodOrField() { int v = 0; bool s = false; string name = null; Token token = lexer.get(); if ( token.code == TokenCode.RBRACE ) // end of class methods { lexer.forget(); return null; } switch ( token.code ) { case TokenCode.PUBLIC : v = 0; lexer.forget(); break; case TokenCode.PRIVATE : v = 1; lexer.forget(); break; case TokenCode.PROTECTED : v = 2; lexer.forget(); break; default: v = 0; break; } token = lexer.get(); if ( token.code == TokenCode.STATIC ) { s = true; lexer.forget(); } TYPE type = null; token = lexer.get(); if ( token.code == TokenCode.VOID ) lexer.forget(); else type = parseType(); token = lexer.get(); if ( token.code == TokenCode.IDENTIFIER ) { name = token.image; lexer.forget(); } else errors.issue(token,11,"identifier"); token = lexer.get(); if ( token.code == TokenCode.SEMICOLON ) { // End of field declaration lexer.forget(); if ( type == null ) errors.issue(token,14); // void in field declaration FIELD field = new FIELD(v,name); field.type = type; field.isStatic = s; return field; } // Else this is a method declaration. METHOD method = new METHOD(v, name); method.isStatic = s; method.type = type; if ( name == "Main" ) { if ( hasMain ) errors.issue(token,32); // multiple Main's else hasMain =true; } // Continue parsing: // "(" [ Parameter {"," Parameter} ] ")" Body token = lexer.get(); if ( token.code != TokenCode.LPAREN ) { errors.issue(token,11,"("); lexer.skipUntil(TokenCode.RPAREN); } else lexer.forget(); int i = 0; while ( true ) // parsing method parameters { token = lexer.get(); if ( token.code == TokenCode.RPAREN ) { lexer.forget(); break; } FIELD parameter = parseParameter(); string n = parameter.name; if ( method.parameters.ContainsKey(n) ) errors.issue(token,12,"parameter",n); else { parameter.number = i; i++; method.parameters.Add(n,parameter); } token = lexer.get(); if (token.code == TokenCode.COMMA) { lexer.forget(); continue; } else if (token.code != TokenCode.RPAREN) { errors.issue(token,16); lexer.skipUntil(TokenCode.RPAREN); lexer.forget(); break; } } // Parsing method body: // // Body ::= "{" {LocalDeclaration} {Statement} "}". token = lexer.get(); if ( token.code == TokenCode.LBRACE ) lexer.forget(); else lexer.skipUntil(TokenCode.RBRACE); int j = 0; while ( true ) { token = lexer.get(); if ( token.code == TokenCode.RBRACE ) { lexer.forget(); break; } ENTITY bodyElement = parseBodyElement(); if ( bodyElement == null ) // and error was detected continue; else if ( bodyElement is FIELD ) { (bodyElement as FIELD).isLocal = true; string n = (bodyElement as FIELD).name; if ( method.locals.ContainsKey(n) ) errors.issue(token,12,"local",n); else { (bodyElement as FIELD).number = j; j++; method.locals.Add(n,bodyElement as FIELD); } } else if ( bodyElement is STATEMENT ) method.statements.Add(bodyElement as STATEMENT); } return method; }
/// <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; } }
private void generateLocal( ILGenerator il, FIELD field ) { TYPE t = field.type; Type type = null; if ( t.classRef == null ) { if ( t.isArray ) type = typeof(int[]); else type = typeof(int); } else { type = classes[t.className].typeBuilder; if ( t.isArray ) type = type.MakeArrayType(); } LocalBuilder local = il.DeclareLocal(type); if ( t.classRef == null ) { if ( t.isArray ) il.Emit(OpCodes.Ldnull); else il.Emit(OpCodes.Ldc_I4_0); } else il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc,local); }