?? parser.java
字號:
/** * @(#)Parser.java 1.39 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.tools.javac.v8.parser;import com.sun.tools.javac.v8.tree.*;import com.sun.tools.javac.v8.code.*;import com.sun.tools.javac.v8.util.*;import com.sun.tools.javac.v8.tree.Tree.*;/** * The parser maps a token sequence into an abstract syntax * tree. It operates by recursive descent, with code derived * systematically from an LL(1) grammar. For efficiency reasons, an * operator precedence scheme is used for parsing binary operation * expressions. */public class Parser implements Tokens { /** * The number of precedence levels of infix operators. */ private static final int infixPrecedenceLevels = 10; /** * The scanner used for lexical analysis. */ private Scanner S; /** * The factory to be used for abstract syntax tree construction. */ private TreeMaker F; /** * The log to be used for error diagnostics. */ private Log log; /** * The keyword table. */ private Keywords keywords; /** * The Source language setting. */ private Source source; /** * The name table. */ private Name.Table names; /** * Construct a parser from a given scanner, tree factory and log. * @param genEndPos Should endPositions be generated? */ public Parser(Context context, Scanner S, boolean keepDocComments, boolean genEndPos) { super(); this.S = S; this.F = TreeMaker.instance(context); this.log = Log.instance(context); this.names = Name.Table.instance(context); this.keywords = Keywords.instance(context); this.keepDocComments = keepDocComments; this.source = Source.instance(context); this.allowAsserts = source.ordinal >= Source.JDK1_4.ordinal; this.genEndPos = genEndPos; if (keepDocComments) docComments = new Hashtable(); if (genEndPos) endPositions = new Hashtable(); } /** * Switch: should we keep docComments? */ boolean keepDocComments; /** * Switch: should we recognize assert statements, or just give a warning? */ boolean allowAsserts; /** * Switch: should we store the ending positions? */ boolean genEndPos; /** * When terms are parsed, the mode determines which is expected: * mode = EXPR : an expression * mode = TYPE : a type * mode = NOPARAMS : no parameters allowed for type */ static final int EXPR = 1; static final int TYPE = 2; static final int NOPARAMS = 4; /** * The current mode. */ private int mode = 0; /** * The mode of the term that was parsed last. */ private int lastmode = 0; static Tree errorTree = new Tree.Erroneous(); /** * Skip forward until a suitable stop token is found. */ private void skip() { int nbraces = 0; int nparens = 0; while (true) { switch (S.token) { case EOF: case CLASS: case INTERFACE: return; case SEMI: if (nbraces == 0 && nparens == 0) return; break; case RBRACE: if (nbraces == 0) return; nbraces--; break; case RPAREN: if (nparens > 0) nparens--; break; case LBRACE: nbraces++; break; case LPAREN: nparens++; break; default: } S.nextToken(); } } /** * Generate a syntax error at given position using the given argument * unless one was already reported at the same position, then skip. */ private Tree syntaxError(int pos, String key, String arg) { if (pos != S.errPos) log.error(pos, key, arg); skip(); S.errPos = pos; return errorTree; } /** * Generate a syntax error at given position unless one was already * reported at the same position, then skip. */ private Tree syntaxError(int pos, String key) { return syntaxError(pos, key, null); } /** * Generate a syntax error at current position unless one was already reported * at the same position, then skip. */ private Tree syntaxError(String key) { return syntaxError(S.pos, key, null); } /** * Generate a syntax error at current position unless one was already reported * at the same position, then skip. */ private Tree syntaxError(String key, String arg) { return syntaxError(S.pos, key, arg); } /** * If next input token matches given token, skip it, otherwise report an error. */ private void accept(int token) { if (S.token == token) { S.nextToken(); } else { int pos = Position.line(S.pos) > Position.line(S.prevEndPos + 1) ? S.prevEndPos + 1 : S.pos; syntaxError(pos, "expected", keywords.token2string(token)); if (S.token == token) S.nextToken(); } } /** * Report an illegal start of expression/type error at given position. */ Tree illegal(int pos) { if ((mode & EXPR) != 0) return syntaxError(pos, "illegal.start.of.expr"); else return syntaxError(pos, "illegal.start.of.type"); } /** * Report an illegal start of expression/type error at current position. */ Tree illegal() { return illegal(S.pos); } /** * A hashtable to store all documentation comments * indexed by the tree nodes they refer to. * defined only if option flag keepDocComment is set. */ Hashtable docComments; /** * Make an entry into docComments hashtable, * provided flag keepDocComments is set and given doc comment is non-null. * @param tree The tree to be used as index in the hashtable * @param dc The doc comment to associate with the tree, or null. */ void attach(Tree tree, String dc) { if (keepDocComments && dc != null) { docComments.put(tree, dc); } } /** * A hashtable to store ending positions * of source ranges indexed by the tree nodes. * Defined only if option flag genEndPos is set. */ Hashtable endPositions; /** * Make an entry into endPositions hashtable, provided flag * genEndPos is set. Note that this method is usually hand-inlined. * @param tree The tree to be used as index in the hashtable * @param endPos The ending position to associate with the tree. */ void storeEnd(Tree tree, int endpos) { if (genEndPos) endPositions.put(tree, new Integer(endpos)); } /** * Ident = IDENTIFIER */ Name ident() { if (S.token == IDENTIFIER) { Name name = S.name; S.nextToken(); return name; } if (S.token == ASSERT) { if (allowAsserts) { log.error(S.pos, "assert.as.identifier"); S.nextToken(); return names.error; } else { log.warning(S.pos, "assert.as.identifier"); Name name = S.name; S.nextToken(); return name; } } else { accept(IDENTIFIER); return names.error; } } /** * Qualident = Ident { DOT Ident } */ Tree qualident() { Tree t = F.at(S.pos).Ident(ident()); while (S.token == DOT) { int pos = S.pos; S.nextToken(); t = F.at(pos).Select(t, ident()); } return t; } /** * Literal = * INTLITERAL * | LONGLITERAL * | FLOATLITERAL * | DOUBLELITERAL * | CHARLITERAL * | STRINGLITERAL * | TRUE * | FALSE * | NULL */ Tree literal(Name prefix) { int pos = S.pos; Tree t = errorTree; switch (S.token) { case INTLITERAL: try { t = F.at(pos).Literal(Type.INT, new Integer(Convert.string2int(strval(prefix), S.radix))); } catch (NumberFormatException ex) { log.error(S.pos, "int.number.too.large", strval(prefix)); } break; case LONGLITERAL: try { t = F.at(pos).Literal(Type.LONG, new Long(Convert.string2long(strval(prefix), S.radix))); } catch (NumberFormatException ex) { log.error(S.pos, "int.number.too.large", strval(prefix)); } break; case FLOATLITERAL: { Float n = Float.valueOf(S.stringVal()); if (n.floatValue() == 0.0F && !isZero(S.stringVal())) log.error(S.pos, "fp.number.too.small"); else if (n.floatValue() == Float.POSITIVE_INFINITY) log.error(S.pos, "fp.number.too.large"); else t = F.at(pos).Literal(Type.FLOAT, n); break; } case DOUBLELITERAL: { Double n = Double.valueOf(S.stringVal()); if (n.doubleValue() == 0.0 && !isZero(S.stringVal())) log.error(S.pos, "fp.number.too.small"); else if (n.doubleValue() == Double.POSITIVE_INFINITY) log.error(S.pos, "fp.number.too.large"); else t = F.at(pos).Literal(Type.DOUBLE, n); break; } case CHARLITERAL: t = F.at(pos).Literal(Type.CHAR, new Integer(S.stringVal().charAt(0))); break; case STRINGLITERAL: t = F.at(pos).Literal(Type.CLASS, S.stringVal()); break; case TRUE: case FALSE: case NULL: t = F.at(pos).Ident(S.name); break; default: assert false; } S.nextToken(); return t; } boolean isZero(String s) { char[] cs = s.toCharArray(); int i = 0; while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; return !(i < cs.length && ('1' <= cs[i] && cs[i] <= '9')); } String strval(Name prefix) { String s = S.stringVal(); return (prefix.len == 0) ? s : prefix + s; } /** * terms can be either expressions or types. */ Tree expression() { return term(EXPR); } Tree type() { return term(TYPE); } Tree term(int newmode) { int prevmode = mode; mode = newmode; Tree t = term(); lastmode = mode; mode = prevmode; return t; } /** * Expression = Expression1 [ExpressionRest] * ExpressionRest = [AssignmentOperator Expression1] * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "&=" | "|=" | "^=" | * "%=" | "<<=" | ">>=" | ">>>=" * Type = Type1 * TypeNoParams = TypeNoParams1 * StatementExpression = Expression * ConstantExpression = Expression */ Tree term() { Tree t = term1(); if ((mode & EXPR) != 0 && S.token == EQ || PLUSEQ <= S.token && S.token <= GTGTGTEQ) return termRest(t); else return t; } Tree termRest(Tree t) { switch (S.token) { case EQ: { int pos = S.pos; S.nextToken(); mode = EXPR; Tree t1 = term(); return F.at(pos).Assign(t, t1); } case PLUSEQ: case SUBEQ: case STAREQ: case SLASHEQ: case PERCENTEQ:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -