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