169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.compiler; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic final class Parser implements TokenId { 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Lex lex; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Parser(Lex lex) { 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.lex = lex; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean hasMore() { return lex.lookAhead() >= 0; } 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* member.declaration 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : method.declaration | field.declaration 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ASTList parseMember(SymbolTable tbl) throws CompileError { 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList mem = parseMember1(tbl); 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (mem instanceof MethodDecl) 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseMethod2(tbl, (MethodDecl)mem); 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return mem; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* A method body is not parsed. 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ASTList parseMember1(SymbolTable tbl) throws CompileError { 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList mods = parseMemberMods(); 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator d; 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean isConstructor = false; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') { 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d = new Declarator(VOID, 0); 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal isConstructor = true; 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d = parseFormalType(tbl); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != Identifier) 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name; 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isConstructor) 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = MethodDecl.initName; 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = lex.getString(); 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d.setVariable(new Symbol(name)); 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isConstructor || lex.lookAhead() == '(') 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseMethod1(tbl, isConstructor, mods, d); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseField(tbl, mods, d); 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* field.declaration 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : member.modifiers 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * formal.type Identifier 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ "=" expression ] ";" 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private FieldDecl parseField(SymbolTable tbl, ASTList mods, 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator d) throws CompileError 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = null; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '=') { 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseExpression(tbl); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c = lex.get(); 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ';') 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new FieldDecl(mods, new ASTList(d, new ASTList(expr))); 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == ',') 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError( 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "only one field can be declared in one declaration", lex); 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* method.declaration 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : member.modifiers 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ formal.type ] 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Identifier "(" [ formal.parameter ( "," formal.parameter )* ] ")" 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * array.dimension 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ THROWS class.type ( "," class.type ) ] 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ( block.statement | ";" ) 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Note that a method body is not parsed. 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private MethodDecl parseMethod1(SymbolTable tbl, boolean isConstructor, 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList mods, Declarator d) 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList parms = null; 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() != ')') 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (true) { 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal parms = ASTList.append(parms, parseFormalParam(tbl)); 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == ',') 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == ')') 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // ')' 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d.addArrayDim(parseArrayDimension()); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isConstructor && d.getArrayDim() > 0) 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList throwsList = null; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == THROWS) { 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (true) { 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throwsList = ASTList.append(throwsList, parseClassType(tbl)); 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ',') 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new MethodDecl(mods, new ASTList(d, 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList.make(parms, throwsList, null))); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Parses a method body. 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md) 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = null; 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ';') 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = parseBlock(tbl); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (body == null) 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = new Stmnt(BLOCK); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal md.sublist(4).setHead(body); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return md; 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* member.modifiers 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : ( FINAL | SYNCHRONIZED | ABSTRACT 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | PUBLIC | PROTECTED | PRIVATE | STATIC 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | VOLATILE | TRANSIENT | STRICT )* 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTList parseMemberMods() { 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList list = null; 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (true) { 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.lookAhead(); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == PRIVATE || t == SYNCHRONIZED || t == STATIC 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == VOLATILE || t == TRANSIENT || t == STRICT) 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal list = new ASTList(new Keyword(lex.get()), list); 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return list; 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* formal.type : ( build-in-type | class.type ) array.dimension 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Declarator parseFormalType(SymbolTable tbl) throws CompileError { 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t) || t == VOID) { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // primitive type 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Declarator(t, dim); 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList name = parseClassType(tbl); 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Declarator(name, dim); 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static boolean isBuiltinType(int t) { 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == INT || t == LONG || t == FLOAT || t == DOUBLE); 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* formal.parameter : formal.type Identifier array.dimension 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Declarator parseFormalParam(SymbolTable tbl) 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator d = parseFormalType(tbl); 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != Identifier) 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = lex.getString(); 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d.setVariable(new Symbol(name)); 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal d.addArrayDim(parseArrayDimension()); 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tbl.append(name, d); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return d; 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* statement : [ label ":" ]* labeled.statement 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * labeled.statement 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : block.statement 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | if.statement 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | while.statement 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | do.statement 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | for.statement 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | switch.statement 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | try.statement 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | return.statement 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | thorw.statement 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | break.statement 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | continue.statement 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | declaration.or.expression 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | ";" 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method may return null (empty statement). 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Stmnt parseStatement(SymbolTable tbl) 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == '{') 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseBlock(tbl); 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == ';') { 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(BLOCK); // empty statement 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == Identifier && lex.lookAhead(1) == ':') { 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // Identifier 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String label = lex.getString(); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // ':' 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl)); 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == IF) 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseIf(tbl); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == WHILE) 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseWhile(tbl); 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == DO) 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseDo(tbl); 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == FOR) 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseFor(tbl); 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == TRY) 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseTry(tbl); 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == SWITCH) 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseSwitch(tbl); 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == SYNCHRONIZED) 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseSynchronized(tbl); 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == RETURN) 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseReturn(tbl); 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == THROW) 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseThrow(tbl); 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == BREAK) 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseBreak(tbl); 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == CONTINUE) 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseContinue(tbl); 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseDeclarationOrExpression(tbl, false); 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* block.statement : "{" statement* "}" 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseBlock(SymbolTable tbl) throws CompileError { 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '{') 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = null; 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl2 = new SymbolTable(tbl); 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() != '}') { 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s = parseStatement(tbl2); 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (s != null) 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s)); 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '}' 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (body == null) 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(BLOCK); // empty block 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return body; 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* if.statement : IF "(" expression ")" statement 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ ELSE statement ] 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseIf(SymbolTable tbl) throws CompileError { 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // IF 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseParExpression(tbl); 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt thenp = parseStatement(tbl); 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt elsep; 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ELSE) { 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal elsep = parseStatement(tbl); 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal elsep = null; 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep))); 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* while.statement : WHILE "(" expression ")" statement 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseWhile(SymbolTable tbl) 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // WHILE 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseParExpression(tbl); 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = parseStatement(tbl); 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr, body); 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* do.statement : DO statement WHILE "(" expression ")" ";" 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseDo(SymbolTable tbl) throws CompileError { 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // DO 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = parseStatement(tbl); 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != WHILE || lex.get() != '(') 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseExpression(tbl); 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')' || lex.get() != ';') 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr, body); 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* for.statement : FOR "(" decl.or.expr expression ";" expression ")" 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * statement 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseFor(SymbolTable tbl) throws CompileError { 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt expr1, expr3; 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr2; 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // FOR 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl2 = new SymbolTable(tbl); 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ';') { 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr1 = null; 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr1 = parseDeclarationOrExpression(tbl2, true); 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ';') 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr2 = null; 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr2 = parseExpression(tbl2); 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ';') 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ')') 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr3 = null; 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr3 = parseExprList(tbl2); 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(") is missing", lex); 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = parseStatement(tbl2); 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr1, new ASTList(expr2, 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new ASTList(expr3, body))); 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}" 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * swtich.block : ( switch.label statement* )* 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * swtich.label : DEFAULT ":" 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | CASE const.expression ":" 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseSwitch(SymbolTable tbl) throws CompileError { 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // SWITCH 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseParExpression(tbl); 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = parseSwitchBlock(tbl); 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr, body); 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError { 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '{') 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl2 = new SymbolTable(tbl); 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s = parseStmntOrCase(tbl2); 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (s == null) 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("empty switch block", lex); 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int op = s.getOperator(); 40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (op != CASE && op != DEFAULT) 41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("no case or default in a switch block", 41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex); 41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = new Stmnt(BLOCK, s); 41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() != '}') { 41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s2 = parseStmntOrCase(tbl2); 41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (s2 != null) { 41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int op2 = s2.getOperator(); 41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (op2 == CASE || op2 == DEFAULT) { 41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2)); 42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s = s2; 42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2)); 42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '}' 42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return body; 42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseStmntOrCase(SymbolTable tbl) throws CompileError { 43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t != CASE && t != DEFAULT) 43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseStatement(tbl); 43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s; 43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == CASE) 43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s = new Stmnt(t, parseExpression(tbl)); 44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s = new Stmnt(DEFAULT); 44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ':') 44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(": is missing", lex); 44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return s; 44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* synchronized.statement : 45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * SYNCHRONIZED "(" expression ")" block.statement 45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseSynchronized(SymbolTable tbl) throws CompileError { 45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // SYNCHRONIZED 45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseExpression(tbl); 45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt body = parseBlock(tbl); 46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr, body); 46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* try.statement 46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : TRY block.statement 46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ CATCH "(" class.type Identifier ")" block.statement ]* 46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * [ FINALLY block.statement ]* 46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseTry(SymbolTable tbl) throws CompileError { 47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // TRY 47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt block = parseBlock(tbl); 47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList catchList = null; 47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() == CATCH) { 47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // CATCH 47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl2 = new SymbolTable(tbl); 48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator d = parseFormalParam(tbl2); 48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (d.getArrayDim() > 0 || d.getType() != CLASS) 48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt b = parseBlock(tbl2); 48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catchList = ASTList.append(catchList, new Pair(d, b)); 48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt finallyBlock = null; 49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == FINALLY) { 49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // FINALLY 49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal finallyBlock = parseBlock(tbl); 49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Stmnt.make(TRY, block, catchList, finallyBlock); 49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* return.statement : RETURN [ expression ] ";" 50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseReturn(SymbolTable tbl) throws CompileError { 50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // RETURN 50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s = new Stmnt(t); 50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() != ';') 50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s.setLeft(parseExpression(tbl)); 50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ';') 50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return s; 51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* throw.statement : THROW expression ";" 51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseThrow(SymbolTable tbl) throws CompileError { 51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // THROW 51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseExpression(tbl); 51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ';') 52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Stmnt(t, expr); 52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* break.statement : BREAK [ Identifier ] ";" 52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseBreak(SymbolTable tbl) 52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseContinue(tbl); 53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* continue.statement : CONTINUE [ Identifier ] ";" 53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseContinue(SymbolTable tbl) 53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); // CONTINUE 53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt s = new Stmnt(t); 54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t2 = lex.get(); 54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t2 == Identifier) { 54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s.setLeft(new Symbol(lex.getString())); 54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t2 = lex.get(); 54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t2 != ';') 54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return s; 55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* declaration.or.expression 55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : [ FINAL ] built-in-type array.dimension declarators 55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | [ FINAL ] class.type array.dimension declarators 55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | expression ';' 55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | expr.list ';' if exprList is true 55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Note: FINAL is currently ignored. This must be fixed 55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in future. 56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseDeclarationOrExpression(SymbolTable tbl, 56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean exprList) 56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (t == FINAL) { 56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.lookAhead(); 56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t)) { 57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.get(); 57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseDeclarators(tbl, new Declarator(t, dim)); 57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == Identifier) { 57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = nextIsClassType(0); 57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i >= 0) 57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead(i) == Identifier) { 58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList name = parseClassType(tbl); 58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseDeclarators(tbl, new Declarator(name, dim)); 58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt expr; 58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exprList) 58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseExprList(tbl); 58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = new Stmnt(EXPR, parseExpression(tbl)); 59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ';') 59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* expr.list : ( expression ',')* expression 59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseExprList(SymbolTable tbl) throws CompileError { 60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt expr = null; 60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt e = new Stmnt(EXPR, parseExpression(tbl)); 60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = (Stmnt)ASTList.concat(expr, new Stmnt(BLOCK, e)); 60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ',') 60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* declarators : declarator [ ',' declarator ]* ';' 61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Stmnt parseDeclarators(SymbolTable tbl, Declarator d) 61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Stmnt decl = null; 61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal decl = (Stmnt)ASTList.concat(decl, 62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Stmnt(DECL, parseDeclarator(tbl, d))); 62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); 62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == ';') 62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return decl; 62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t != ',') 62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("; is missing", lex); 62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* declarator : Identifier array.dimension [ '=' initializer ] 63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Declarator parseDeclarator(SymbolTable tbl, Declarator d) 63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != Identifier || d.getType() == VOID) 63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = lex.getString(); 63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Symbol symbol = new Symbol(name); 63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree init = null; 64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '=') { 64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal init = parseInitializer(tbl); 64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator decl = d.make(symbol, dim, init); 64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tbl.append(name, decl); 64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return decl; 64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* initializer : expression | array.initializer 65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseInitializer(SymbolTable tbl) throws CompileError { 65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '{') 65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseArrayInitializer(tbl); 65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseExpression(tbl); 65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* array.initializer : 66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * '{' (( array.initializer | expression ) ',')* '}' 66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ArrayInit parseArrayInitializer(SymbolTable tbl) 66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '{' 66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseExpression(tbl); 66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ArrayInit init = new ArrayInit(expr); 66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() == ',') { 67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseExpression(tbl); 67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList.append(init, expr); 67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '}') 67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return init; 67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* par.expression : '(' expression ')' 68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseParExpression(SymbolTable tbl) throws CompileError { 68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseExpression(tbl); 68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* expression : conditional.expr 69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | conditional.expr assign.op expression (right-to-left) 69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ASTree parseExpression(SymbolTable tbl) throws CompileError { 69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree left = parseConditionalExpr(tbl); 69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!isAssignOp(lex.lookAhead())) 70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return left; 70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); 70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree right = parseExpression(tbl); 70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return AssignExpr.makeAssign(t, left, right); 70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static boolean isAssignOp(int t) { 70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return t == '=' || t == MOD_E || t == AND_E 70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == MUL_E || t == PLUS_E || t == MINUS_E || t == DIV_E 71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == EXOR_E || t == OR_E || t == LSHIFT_E 71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == RSHIFT_E || t == ARSHIFT_E; 71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* conditional.expr (right-to-left) 71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : logical.or.expr [ '?' expression ':' conditional.expr ] 71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseConditionalExpr(SymbolTable tbl) throws CompileError { 71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree cond = parseBinaryExpr(tbl); 71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '?') { 72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree thenExpr = parseExpression(tbl); 72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ':') 72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(": is missing", lex); 72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree elseExpr = parseExpression(tbl); 72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new CondExpr(cond, thenExpr, elseExpr); 72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cond; 73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* logical.or.expr 10 (operator precedence) 73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : logical.and.expr 73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | logical.or.expr OROR logical.and.expr left-to-right 73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * logical.and.expr 9 73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : inclusive.or.expr 73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | logical.and.expr ANDAND inclusive.or.expr 73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * inclusive.or.expr 8 74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : exclusive.or.expr 74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | inclusive.or.expr "|" exclusive.or.expr 74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * exclusive.or.expr 7 74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : and.expr 74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | exclusive.or.expr "^" and.expr 74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and.expr 6 74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : equality.expr 75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | and.expr "&" equality.expr 75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * equality.expr 5 75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : relational.expr 75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | equality.expr (EQ | NEQ) relational.expr 75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * relational.expr 4 75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : shift.expr 75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | relational.expr (LE | GE | "<" | ">") shift.expr 75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | relational.expr INSTANCEOF class.type ("[" "]")* 76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * shift.expr 3 76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : additive.expr 76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | shift.expr (LSHIFT | RSHIFT | ARSHIFT) additive.expr 76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * additive.expr 2 76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : multiply.expr 76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | additive.expr ("+" | "-") multiply.expr 76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * multiply.expr 1 77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * : unary.expr 77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | multiply.expr ("*" | "/" | "%") unary.expr 77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseBinaryExpr(SymbolTable tbl) throws CompileError { 77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parseUnaryExpr(tbl); 77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int p = getOpPrecedence(t); 77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (p == 0) 77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = binaryExpr2(tbl, expr, p); 78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseInstanceOf(SymbolTable tbl, ASTree expr) 78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t)) { 79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // primitive type 79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new InstanceOfExpr(t, dim, expr); 79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList name = parseClassType(tbl); 79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new InstanceOfExpr(name, dim, expr); 79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec) 80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.get(); 80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == INSTANCEOF) 80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseInstanceOf(tbl, expr); 80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr2 = parseUnaryExpr(tbl); 80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t2 = lex.lookAhead(); 81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int p2 = getOpPrecedence(t2); 81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (p2 != 0 && prec > p2) 81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr2 = binaryExpr2(tbl, expr2, p2); 81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return BinExpr.makeBin(t, expr, expr2); 81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // !"#$%&'( )*+,-./0 12345678 9:;<=>? 82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static final int[] binaryOpPrecedence 82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = { 0, 0, 0, 0, 1, 6, 0, 0, 82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 0, 1, 2, 0, 2, 0, 1, 0, 82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 0, 0, 0, 0, 0, 0, 0, 0, 82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 0, 0, 0, 4, 0, 4, 0 }; 82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int getOpPrecedence(int c) { 82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if ('!' <= c && c <= '?') 82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return binaryOpPrecedence[c - '!']; 82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == '^') 83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 7; 83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == '|') 83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 8; 83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == ANDAND) 83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 9; 83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == OROR) 83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 10; 83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == EQ || c == NEQ) 83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 5; 83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == LE || c == GE || c == INSTANCEOF) 84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 4; 84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == LSHIFT || c == RSHIFT || c == ARSHIFT) 84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 3; 84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 0; // not a binary operator 84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* unary.expr : "++"|"--" unary.expr 84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal | "+"|"-" unary.expr 84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal | "!"|"~" unary.expr 85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal | cast.expr 85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal | postfix.expr 85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal unary.expr.not.plus.minus is a unary expression starting without 85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "+", "-", "++", or "--". 85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseUnaryExpr(SymbolTable tbl) throws CompileError { 85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (lex.lookAhead()) { 85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '+' : 86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '-' : 86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case PLUSPLUS : 86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case MINUSMINUS : 86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '!' : 86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '~' : 86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.get(); 86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == '-') { 86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t2 = lex.lookAhead(); 86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (t2) { 86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case LongConstant : 87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case IntConstant : 87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case CharConstant : 87269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 87369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new IntConst(-lex.getLong(), t2); 87469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case DoubleConstant : 87569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case FloatConstant : 87669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 87769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new DoubleConst(-lex.getDouble(), t2); 87869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 87969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 88069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 88369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Expr.make(t, parseUnaryExpr(tbl)); 88469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '(' : 88569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseCast(tbl); 88669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 88769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parsePostfix(tbl); 88869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 88969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 89069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 89169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* cast.expr : "(" builtin.type ("[" "]")* ")" unary.expr 89269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal | "(" class.type ("[" "]")* ")" unary.expr2 89369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 89469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal unary.expr2 is a unary.expr beginning with "(", NULL, StringL, 89569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Identifier, THIS, SUPER, or NEW. 89669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 89769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Either "(int.class)" or "(String[].class)" is a not cast expression. 89869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 89969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseCast(SymbolTable tbl) throws CompileError { 90069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(1); 90169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t) && nextIsBuiltinCast()) { 90269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '(' 90369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // primitive type 90469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 90569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 90669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(") is missing", lex); 90769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 90869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new CastExpr(t, dim, parseUnaryExpr(tbl)); 90969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 91069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == Identifier && nextIsClassCast()) { 91169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '(' 91269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList name = parseClassType(tbl); 91369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 91469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 91569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(") is missing", lex); 91669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 91769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new CastExpr(name, dim, parseUnaryExpr(tbl)); 91869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 91969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 92069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parsePostfix(tbl); 92169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 92269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 92369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean nextIsBuiltinCast() { 92469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 92569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 2; 92669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((t = lex.lookAhead(i++)) == '[') 92769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead(i++) != ']') 92869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 92969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 93069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return lex.lookAhead(i - 1) == ')'; 93169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 93269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 93369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean nextIsClassCast() { 93469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = nextIsClassType(1); 93569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 0) 93669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 93769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 93869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(i); 93969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t != ')') 94069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 94169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 94269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.lookAhead(i + 1); 94369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return t == '(' || t == NULL || t == StringL 94469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == Identifier || t == THIS || t == SUPER || t == NEW 94569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == TRUE || t == FALSE || t == LongConstant 94669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == IntConstant || t == CharConstant 94769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || t == DoubleConstant || t == FloatConstant; 94869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 94969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 95069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int nextIsClassType(int i) { 95169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 95269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead(++i) == '.') 95369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead(++i) != Identifier) 95469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; 95569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 95669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((t = lex.lookAhead(i++)) == '[') 95769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead(i++) != ']') 95869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; 95969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 96069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return i - 1; 96169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 96269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 96369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* array.dimension : [ "[" "]" ]* 96469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 96569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int parseArrayDimension() throws CompileError { 96669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int arrayDim = 0; 96769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() == '[') { 96869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++arrayDim; 96969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 97069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ']') 97169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("] is missing", lex); 97269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 97369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 97469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return arrayDim; 97569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 97669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 97769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* class.type : Identifier ( "." Identifier )* 97869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 97969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTList parseClassType(SymbolTable tbl) throws CompileError { 98069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList list = null; 98169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 98269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != Identifier) 98369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 98469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 98569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal list = ASTList.append(list, new Symbol(lex.getString())); 98669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '.') 98769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 98869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 98969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 99069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 99169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 99269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return list; 99369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 99469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 99569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* postfix.expr : number.literal 99669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | primary.expr 99769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | method.expr 99869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "++" | "--" 99969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "[" array.size "]" 100069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "." Identifier 100169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr ( "[" "]" )* "." CLASS 100269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "#" Identifier 100369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 100469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * "#" is not an operator of regular Java. It separates 100569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a class name and a member name in an expression for static member 100669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * access. For example, 100769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * java.lang.Integer.toString(3) in regular Java 100869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * can be written like this: 100969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * java.lang.Integer#toString(3) for this compiler. 101069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 101169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parsePostfix(SymbolTable tbl) throws CompileError { 101269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int token = lex.lookAhead(); 101369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (token) { // see also parseUnaryExpr() 101469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case LongConstant : 101569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case IntConstant : 101669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case CharConstant : 101769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 101869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new IntConst(lex.getLong(), token); 101969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case DoubleConstant : 102069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case FloatConstant : 102169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 102269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new DoubleConst(lex.getDouble(), token); 102369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 102469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 102569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 102669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 102769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String str; 102869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree index; 102969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr = parsePrimaryExpr(tbl); 103069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 103169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (true) { 103269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (lex.lookAhead()) { 103369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '(' : 103469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseMethodCall(tbl, expr); 103569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 103669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '[' : 103769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead(1) == ']') { 103869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 103969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '.' || lex.get() != CLASS) 104069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 104169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 104269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseDotClass(expr, dim); 104369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 104469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 104569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = parseArrayIndex(tbl); 104669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (index == null) 104769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 104869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 104969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = Expr.make(ARRAY, expr, index); 105069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 105169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 105269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case PLUSPLUS : 105369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case MINUSMINUS : 105469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.get(); 105569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = Expr.make(t, null, expr); 105669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 105769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '.' : 105869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 105969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.get(); 106069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == CLASS) { 106169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseDotClass(expr, 0); 106269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 106369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == Identifier) { 106469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal str = lex.getString(); 106569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = Expr.make('.', expr, new Member(str)); 106669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 106769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 106869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("missing member name", lex); 106969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 107069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '#' : 107169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 107269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.get(); 107369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t != Identifier) 107469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("missing static member name", lex); 107569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 107669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal str = lex.getString(); 107769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = Expr.make(MEMBER, new Symbol(toClassName(expr)), 107869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Member(str)); 107969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 108069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 108169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 108269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 108369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 108469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 108569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 108669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Parse a .class expression on a class type. For example, 108769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * String.class => ('.' "String" "class") 108869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * String[].class => ('.' "[LString;" "class") 108969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 109069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseDotClass(ASTree className, int dim) 109169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 109269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 109369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cname = toClassName(className); 109469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (dim > 0) { 109569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(); 109669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (dim-- > 0) 109769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append('['); 109869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 109969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append('L').append(cname.replace('.', '/')).append(';'); 110069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = sbuf.toString(); 110169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 110269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 110369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Expr.make('.', new Symbol(cname), new Member("class")); 110469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 110569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 110669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Parses a .class expression on a built-in type. For example, 110769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * int.class => ('#' "java.lang.Integer" "TYPE") 110869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * int[].class => ('.' "[I", "class") 110969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 111069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseDotClass(int builtinType, int dim) 111169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 111269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 111369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (dim > 0) { 111469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cname = CodeGen.toJvmTypeName(builtinType, dim); 111569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Expr.make('.', new Symbol(cname), new Member("class")); 111669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 111769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 111869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cname; 111969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch(builtinType) { 112069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case BOOLEAN : 112169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Boolean"; 112269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 112369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case BYTE : 112469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Byte"; 112569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 112669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case CHAR : 112769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Character"; 112869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 112969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case SHORT : 113069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Short"; 113169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 113269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case INT : 113369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Integer"; 113469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 113569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case LONG : 113669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Long"; 113769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 113869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case FLOAT : 113969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Float"; 114069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 114169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case DOUBLE : 114269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Double"; 114369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 114469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case VOID : 114569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = "java.lang.Void"; 114669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 114769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 114869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("invalid builtin type: " 114969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + builtinType); 115069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 115169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 115269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE")); 115369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 115469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 115569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 115669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* method.call : method.expr "(" argument.list ")" 115769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * method.expr : THIS | SUPER | Identifier 115869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "." Identifier 115969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | postfix.expr "#" Identifier 116069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 116169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseMethodCall(SymbolTable tbl, ASTree expr) 116269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 116369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 116469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (expr instanceof Keyword) { 116569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int token = ((Keyword)expr).get(); 116669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (token != THIS && token != SUPER) 116769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 116869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 116969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (expr instanceof Symbol) // Identifier 117069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ; 117169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (expr instanceof Expr) { 117269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int op = ((Expr)expr).getOperator(); 117369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (op != '.' && op != MEMBER) 117469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 117569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 117669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 117769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return CallExpr.makeCall(expr, parseArgumentList(tbl)); 117869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 117969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 118069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String toClassName(ASTree name) 118169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 118269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 118369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(); 118469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toClassName(name, sbuf); 118569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return sbuf.toString(); 118669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 118769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 118869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void toClassName(ASTree name, StringBuffer sbuf) 118969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 119069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 119169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name instanceof Symbol) { 119269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(((Symbol)name).get()); 119369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 119469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 119569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name instanceof Expr) { 119669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Expr expr = (Expr)name; 119769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (expr.getOperator() == '.') { 119869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toClassName(expr.oprand1(), sbuf); 119969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append('.'); 120069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toClassName(expr.oprand2(), sbuf); 120169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 120269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 120369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 120469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 120569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("bad static member access", lex); 120669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 120769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 120869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL 120969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | StringL 121069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | Identifier 121169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | NEW new.expr 121269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | "(" expression ")" 121369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | builtin.type ( "[" "]" )* "." CLASS 121469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 121569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Identifier represents either a local variable name, a member name, 121669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or a class name. 121769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 121869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parsePrimaryExpr(SymbolTable tbl) throws CompileError { 121969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t; 122069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name; 122169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator decl; 122269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree expr; 122369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 122469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (t = lex.get()) { 122569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case THIS : 122669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case SUPER : 122769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case TRUE : 122869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case FALSE : 122969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case NULL : 123069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Keyword(t); 123169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case Identifier : 123269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = lex.getString(); 123369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal decl = tbl.lookup(name); 123469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (decl == null) 123569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Member(name); // this or static member 123669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 123769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Variable(name, decl); // local variable 123869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case StringL : 123969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new StringL(lex.getString()); 124069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case NEW : 124169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseNew(tbl); 124269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '(' : 124369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr = parseExpression(tbl); 124469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() == ')') 124569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return expr; 124669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 124769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(") is missing", lex); 124869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 124969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t) || t == VOID) { 125069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = parseArrayDimension(); 125169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() == '.' && lex.get() == CLASS) 125269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return parseDotClass(t, dim); 125369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 125469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 125569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 125669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 125769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 125869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 125969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* new.expr : class.type "(" argument.list ")" 126069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | class.type array.size [ array.initializer ] 126169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * | primitive.type array.size [ array.initializer ] 126269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 126369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private NewExpr parseNew(SymbolTable tbl) throws CompileError { 126469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ArrayInit init = null; 126569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int t = lex.lookAhead(); 126669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isBuiltinType(t)) { 126769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 126869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList size = parseArraySize(tbl); 126969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '{') 127069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal init = parseArrayInitializer(tbl); 127169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 127269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new NewExpr(t, size, init); 127369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 127469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == Identifier) { 127569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList name = parseClassType(tbl); 127669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal t = lex.lookAhead(); 127769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (t == '(') { 127869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList args = parseArgumentList(tbl); 127969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new NewExpr(name, args); 128069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 128169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (t == '[') { 128269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList size = parseArraySize(tbl); 128369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == '{') 128469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal init = parseArrayInitializer(tbl); 128569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 128669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return NewExpr.makeObjectArray(name, size, init); 128769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 128869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 128969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 129069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new SyntaxError(lex); 129169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 129269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 129369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* array.size : [ array.index ]* 129469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 129569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTList parseArraySize(SymbolTable tbl) throws CompileError { 129669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList list = null; 129769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (lex.lookAhead() == '[') 129869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal list = ASTList.append(list, parseArrayIndex(tbl)); 129969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 130069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return list; 130169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 130269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 130369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* array.index : "[" [ expression ] "]" 130469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 130569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError { 130669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); // '[' 130769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ']') { 130869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 130969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 131069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 131169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 131269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree index = parseExpression(tbl); 131369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ']') 131469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("] is missing", lex); 131569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 131669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return index; 131769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 131869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 131969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 132069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* argument.list : "(" [ expression [ "," expression ]* ] ")" 132169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 132269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private ASTList parseArgumentList(SymbolTable tbl) throws CompileError { 132369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != '(') 132469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("( is missing", lex); 132569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 132669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList list = null; 132769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() != ')') 132869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 132969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal list = ASTList.append(list, parseExpression(tbl)); 133069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.lookAhead() == ',') 133169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lex.get(); 133269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 133369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 133469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 133569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 133669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (lex.get() != ')') 133769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(") is missing", lex); 133869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 133969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return list; 134069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 134169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 134269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1343