scanner.java

来自「数据仓库展示程序」· Java 代码 · 共 540 行 · 第 1/2 页

JAVA
540
字号
/*
// $Id: //open/mondrian/src/main/mondrian/olap/Scanner.java#10 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// (C) Copyright 1998-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 20 January, 1999
*/

package mondrian.olap;

import java_cup.runtime.Symbol;
import org.apache.log4j.Logger;
import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.IOException;

/**
 * Lexical analyzer for MDX.
 */
public class Scanner {
    private static final Logger LOGGER = Logger.getLogger(Scanner.class);

    /** single lookahead character */
    protected int nextChar;
    /** next lookahead character */
    private int lookaheadChar = 0;
    private Hashtable m_resWordsTable;
    private int iMaxResword;
    private String m_aResWords[];
    protected boolean debug;
    private List lines;        // lines[x] is the start of the x'th line
    private int iChar;          // number of times advance() has been called
    private int iPrevChar;      // end of previous token
    private int previousSymbol; // previous symbol returned
    private boolean inFormula;

    Scanner(boolean debug) {
        this.debug = debug;
    }

    /* Advance input by one character, setting {@link #nextChar}. */
    private final void advance()
        throws java.io.IOException {

        if (lookaheadChar == 0) {
            // We have not called lookahead().
            nextChar = getChar();
        } else {
            // We have called lookahead(); advance to the character it got.
            nextChar = lookaheadChar;
            lookaheadChar = 0;
        }
        if (nextChar == '\012') {
            lines.add(new Integer(iChar));
        }
        iChar++;
    }

    /** Peek at the character after {@link #nextChar} without advancing. */
    private final int lookahead()
        throws java.io.IOException {

        lookaheadChar = getChar();
        return lookaheadChar;
    }

    /** Read a character from input, returning -1 if end of input. */
    protected int getChar()
        throws java.io.IOException {

        return System.in.read();
    }

    /** Initialize the scanner */
    public void init()
        throws java.io.IOException {

        initReswords();
        lines = new ArrayList();
        iChar = iPrevChar = 0;
        advance();
    }

    /**
     * Deduces the line and column (0-based) of a symbol.
     * Called by {@link Parser#syntax_error}.
     */
    void getLocation(Symbol symbol, int[] loc) {
        int iTarget = symbol.left;
        int iLine = -1;
        int iLineEnd = 0;
        int iLineStart;
        do {
            iLine++;
            iLineStart = iLineEnd;
            iLineEnd = Integer.MAX_VALUE;
            if (iLine < lines.size()) {
                iLineEnd = ((Integer) lines.get(iLine)).intValue();
            }
        } while (iLineEnd < iTarget);

        loc[0] = iLine; // line
        loc[1] = iTarget - iLineStart; // column
    }

    private Symbol trace(Symbol s) {
        if (debug) {
            String name = null;
            if (s.sym < m_aResWords.length) {
                name = m_aResWords[s.sym];
            }

            LOGGER.error("Scanner returns #" + s.sym +
                (name == null ? "" : ":" + name) +
                (s.value == null ? "" : "(" + s.value.toString() + ")"));
        }
        return s;
    }

    private void initResword(int id, String s) {
        m_resWordsTable.put(s, new Integer(id));
        if (id > iMaxResword) {
            iMaxResword = id;
        }
    }

    private void initReswords() {
        // This list generated by piping the 'terminal' declaration in mdx.cup
        // through:
        //   grep -list // |
        //   sed -e 's/,//' |
        //   awk '{printf "initResword(%20s,%c%s%c);",$1,34,$1,34}'
        m_resWordsTable = new Hashtable();
        iMaxResword = 0;
//      initResword(ParserSym.ALL                 ,"ALL");
        initResword(ParserSym.AND                 ,"AND");
        initResword(ParserSym.AS                  ,"AS");
//      initResword(ParserSym.ASC                 ,"ASC");
        initResword(ParserSym.AXIS                ,"AXIS");
//      initResword(ParserSym.BACK_COLOR          ,"BACK_COLOR");
//      initResword(ParserSym.BASC                ,"BASC");
//      initResword(ParserSym.BDESC               ,"BDESC");
        initResword(ParserSym.CASE                ,"CASE");
        initResword(ParserSym.CELL                ,"CELL");
//      initResword(ParserSym.CELL_ORDINAL        ,"CELL_ORDINAL");
//      initResword(ParserSym.CHAPTERS            ,"CHAPTERS");
//      initResword(ParserSym.CHILDREN            ,"CHILDREN");
//      initResword(ParserSym.COLUMNS             ,"COLUMNS");
//      initResword(ParserSym.DESC                ,"DESC");
        initResword(ParserSym.DIMENSION           ,"DIMENSION");
        initResword(ParserSym.ELSE                ,"ELSE");
        initResword(ParserSym.EMPTY               ,"EMPTY");
        initResword(ParserSym.END                 ,"END");
//      initResword(ParserSym.FIRSTCHILD          ,"FIRSTCHILD");
//      initResword(ParserSym.FIRSTSIBLING        ,"FIRSTSIBLING");
//      initResword(ParserSym.FONT_FLAGS          ,"FONT_FLAGS");
//      initResword(ParserSym.FONT_NAME           ,"FONT_NAME");
//      initResword(ParserSym.FONT_SIZE           ,"FONT_SIZE");
//      initResword(ParserSym.FORE_COLOR          ,"FORE_COLOR");
//      initResword(ParserSym.FORMATTED_VALUE     ,"FORMATTED_VALUE");
//      initResword(ParserSym.FORMAT_STRING       ,"FORMAT_STRING");
        initResword(ParserSym.FROM                ,"FROM");
        initResword(ParserSym.IS                  ,"IS");
//      initResword(ParserSym.LAG                 ,"LAG");
//      initResword(ParserSym.LASTCHILD           ,"LASTCHILD");
//      initResword(ParserSym.LASTSIBLING         ,"LASTSIBLING");
//      initResword(ParserSym.LEAD                ,"LEAD");
        initResword(ParserSym.MEMBER              ,"MEMBER");
//      initResword(ParserSym.MEMBERS             ,"MEMBERS");
//      initResword(ParserSym.NEXTMEMBER          ,"NEXTMEMBER");
        initResword(ParserSym.NON                 ,"NON");
        initResword(ParserSym.NOT                 ,"NOT");
        initResword(ParserSym.NULL                ,"NULL");
        initResword(ParserSym.ON                  ,"ON");
        initResword(ParserSym.OR                  ,"OR");
//      initResword(ParserSym.PAGES               ,"PAGES");
//      initResword(ParserSym.PARENT              ,"PARENT");
//      initResword(ParserSym.PREVMEMBER          ,"PREVMEMBER");
        initResword(ParserSym.PROPERTIES          ,"PROPERTIES");
//      initResword(ParserSym.RECURSIVE           ,"RECURSIVE");
//      initResword(ParserSym.ROWS                ,"ROWS");
//      initResword(ParserSym.SECTIONS            ,"SECTIONS");
        initResword(ParserSym.SELECT              ,"SELECT");
        initResword(ParserSym.SET                 ,"SET");
//      initResword(ParserSym.SOLVE_ORDER         ,"SOLVE_ORDER");
        initResword(ParserSym.THEN                ,"THEN");
//      initResword(ParserSym.VALUE               ,"VALUE");
        initResword(ParserSym.WHEN                ,"WHEN");
        initResword(ParserSym.WHERE               ,"WHERE");
        initResword(ParserSym.WITH                ,"WITH");
        initResword(ParserSym.XOR                 ,"XOR");

        m_aResWords = new String[iMaxResword + 1];
        Enumeration e = m_resWordsTable.keys();
        while (e.hasMoreElements()) {
            Object o = e.nextElement();
            String s = (String) o;
            int i = ((Integer) m_resWordsTable.get(s)).intValue();
            m_aResWords[i] = s;
        }
    }

    /** return the name of the reserved word whose token code is "i" */
    public String lookupReserved(int i) {
        return m_aResWords[i];
    }

    private Symbol makeSymbol(int id,Object o) {
        int iPrevPrevChar = iPrevChar;
        this.iPrevChar = iChar;
        this.previousSymbol = id;
        return trace(new Symbol(id, iPrevPrevChar, iChar, o));
    }
    private Symbol makeNumber(double mantissa, int exponent) {
        double d = mantissa * java.lang.Math.pow(10, exponent);
        return makeSymbol(ParserSym.NUMBER, new Double(d));
    }

    private Symbol makeId(String s, boolean quoted, boolean ampersand) {
        return makeSymbol(
            quoted && ampersand ? ParserSym.AMP_QUOTED_ID :
            quoted ? ParserSym.QUOTED_ID :
            ParserSym.ID,
            s);
    }

    private Symbol makeRes(int i) {
        return makeSymbol(i, m_aResWords[i]);
    }

    private Symbol makeToken(int i, String s) {
        return makeSymbol(i, s);
    }

    private Symbol makeString( String s ) {
        return makeSymbol(ParserSym.STRING, s);
    }

    /**
     * Recognizes and returns the next complete token.
     */
    public Symbol next_token() throws IOException {

        StringBuffer id;
        boolean ampersandId = false;
        for (;;) {
            switch (nextChar) {
            case '.':
                switch (lookahead()) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    // We're looking at the '.' on the start of a number,
                    // e.g. .1; fall through to parse a number.
                    break;
                default:
                    advance();
                    return makeToken(ParserSym.DOT, ".");
                }
                // fall through

            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':

                // Parse a number.  Valid examples include 1, 1.2, 0.1, .1,

⌨️ 快捷键说明

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