⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/**
 * @(#)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 {

    /**
     * 操作符的优先级,后面的算符优先算法会用到
     */
    private static final int infixPrecedenceLevels = 10;

    /**
     * 词法分析类
     */
    private Scanner S;

    /**
     * 语法树构造工厂
     */
    private TreeMaker F;

    /**
     * 错误诊断的log信息
     */
    private Log log;

    /**
     * 关键字表
     */
    private Keywords keywords;

    /**
     * 对源语言设置的类
     */
    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);
    }

    /**
      * 如果下一个输入的字符和前一个匹配则继续,否则抛出错误。
      */
    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();
        }
    }

    /**
      * 报告表达式或类型起始错误
      */
    Tree illegal(int pos) {
        if ((mode & EXPR) != 0)
            return syntaxError(pos, "illegal.start.of.expr");
        else
            return syntaxError(pos, "illegal.start.of.type");
    }

    /**
      * 报告当前位置表达式或类型起始错误
      */
    Tree illegal() {
        return illegal(S.pos);
    }

    /**
      *用来存放文件注释的hashtable
      */
    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) {//判断是否识别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;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -