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

📄 parser.java

📁 JAVA 数学程序库 提供常规的数值计算程序包
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
package jmathlib.core.interpreter;

import jmathlib.core.tokens.*;
import jmathlib.core.tokens.numbertokens.*;
import jmathlib.core.constants.*;

import java.util.Vector;
import java.util.Stack;

/**The parser uses the Lexer to produce a list of tokens which it builds into an abstract syntax tree. */
public class Parser extends RootObject implements TokenConstants, ErrorCodes
{
    /** the token which is currently processed */
    private Token   currentToken      = null;
    
    /** the token which will be parsed next */
    private Token   peekNextToken     = null;
    
    /** indicator wether the next token to be parsed was already requested from the 
        lexical analyser */
    private    boolean peekNextTokenBool = false;
    
    /**The lexical analyser which separates an expression into tokens*/
    private LexicalAnalyser lex = new LexicalAnalyser();

    //private boolean endOfTokens = false;

    /** */
    public String evaluationLockWords;

    
    /**default constructor - creates the Parser object with an empty string*/
    public Parser()
    {
        evaluationLockWords += " global isglobal ";
    }

    /**Parse an expression and return an operand tree of the expression
    @param expression = a vector of tokens
    @return the parsed expressions as a tree of operands*/
    public OperandToken parseExpression(String expression)
    {
        // show indention for every logging message
    	ErrorLogger.setDisplayIndent(true);

        lex.analyseExpression(expression);
        //endOfTokens = false;

        // parse ALL available Tokens
        OperandToken expr = parseCommandList();             
        
        ErrorLogger.setDisplayIndent(false);
        return expr; 
    }

    /** set expression of a m-function file or m-script file.
    This method is used for parsing m-scripts/functions. 
    @param expression = code of a function as a string*/
    public void setExpression(String expression)
    {
    	// display indention while parsing
        ErrorLogger.setDisplayIndent(true);

        lex.analyseExpression(expression);
        //endOfTokens = false;

        ErrorLogger.setDisplayIndent(false);
    }

    /** parse remaining tokens of a m-function file or m-script file 
    @return the parsed expresssion*/
    public OperandToken parseRemainingExpression()
    {
    	// display indention while parsing
        ErrorLogger.setDisplayIndent(true);

        // parse ALL available Tokens
        OperandToken expr = parseCommandList();             
        
        ErrorLogger.setDisplayIndent(false);
        return expr; 
    }
            
    /** return the currently scanned line of code to identify the 
    possible errors. (e.g. a=sin(3]+4  is an eroror and  
    returns a=sin(3] to display to the user
    @return the currently scanned line of code */ 
    public String getScannedLineOfCode()
    {
        return lex.getScannedLineOfCode();
    }
            
/*****************************************************************************/
/* Methods to return/inspect/work on single tokens returned from the scanner */

    /**get next token from the lexical analyser
    @return the next token*/
    public Token getNextToken()
    {
        return getNextToken(SINGLE);
    }

    /**get next token from the lexical analyser
    @param indicator if lexical analyser should consider whitespaces or not
    @return the next token*/
    private Token getNextToken(int type)
    {
        //ErrorLogger.debugLine("Parser: getNextToken");

        // copy peek next token to next token OR get new next token
        if (!peekNextTokenBool)
        {
            currentToken     =  lex.getNextToken(type);
        }
        else
        {
            currentToken      = peekNextToken;
            peekNextTokenBool = false;
        }

        return currentToken;
    }
    
    /**get next Token from lexical analyser, without moving forward
    @return the next token*/
    public Token peekNextToken()
    {
        return peekNextToken(SINGLE);
    }

    /**get next Token from lexical analyser, without moving forward
    @param indicator if lexical analyser should consider whitespaces or not
    @return the next token*/
    private Token peekNextToken(int type)
    {
        //ErrorLogger.debugLine("Parser: peekNextToken");
        
        if (!peekNextTokenBool)
        {
            peekNextToken     = lex.getNextToken(type);
            peekNextTokenBool = true;

            //if (peekNextToken == null)
            //    endOfTokens = true;
        }

           return peekNextToken;
    }

/*****************************************************************************/

    /**parse the expression contained in exp, this method is also called recursivly 
     to find the parameters of functions and matrices                             
    @param deliTyp - shows whether parser is parsing expressions or a matrix 
    @return the parsed operand/expression */
    private OperandToken parseSingle(Stack operandStack, int deliTyp)
    {
        //         ==SINGLE, this is a parameter of a function (e.g.: sin(3) or 3 or a )
        //         ==MATRIX, also consider whitespaces during parsing of matrices
        if (deliTyp==MATRIX) ErrorLogger.debugLine("Parser parseSingle matrix");
        else                 ErrorLogger.debugLine("Parser parseSingle"); 

        ErrorLogger.increaseIndent();

 
        //      parsing is not useful if the next token will be a closing ")"
        // (e.g. who() or a.getColor() )
        //if (    isExpectedDelimiter(peekNextToken(), "elseif") ||
        //		isExpectedDelimiter(peekNextToken(), "else")   ||
		//		isExpectedDelimiter(peekNextToken(), "end")       )
        //{
        //	ErrorLogger.decreaseIndent();
        //	ErrorLogger.debugLine("Parser deli return");
        //	return null; 
        //}

        
        OperandToken retToken  = null;                    // holds token to be returned
        Token        peekToken = peekNextToken(deliTyp); // holds next (actual) token
        
        if (peekToken == null)
        {
            // No more tokens available
            // Do nothing
        }
        else if(peekToken instanceof DelimiterToken)
        {
            DelimiterToken token = ((DelimiterToken)peekToken);

            if (token.value == '(' ) 
            {
                ErrorLogger.debugLine("Parser: found (");
                getNextToken(deliTyp); // remove (

                //parse expression, e.g.: (a+1)+2                    
                retToken = parseArithExpression(SINGLE);         
                
                // get current token to see if closing ')'
                if (!isExpectedDelimiter(peekNextToken(deliTyp), ')' )) 
                    Errors.throwParserException(" missing )");
                else
                    getNextToken(deliTyp);

                // (e.g. (2+3) is hidden inside in expression to avoid problems with
                // expressions of higher priority. (e.g. (2+3)*4 )
                retToken = new Expression(null, retToken);
                
            }
            else if (token.value == '[')
            {
                ErrorLogger.debugLine("Parser: matrix begin [");
                getNextToken(deliTyp); // remove [
                
                retToken = parseMatrix();
                
                //ErrorLogger.debugLine("Parser: Matrix: ] end");        
            }
            else if (token.value == '{')
            {
                ErrorLogger.debugLine("Parser: cell array begin {");
                getNextToken(deliTyp); // remove {
                
                retToken = parseCellArray();
                
                //ErrorLogger.debugLine("Parser: CellArray: ] end");        
            }
            else
            {
                // Delimiter: ] , ; \r \n ) } - 
            	//      end, endif, elseif, else
                // The parser found an unspecified delimiter, this can mark 
                //   the end of a parameter
                //   or the end of a function
                //   or the end of a line/command 
                // The delimiter will be consumed by a the parser function
                //   which is expecting a delimiter
                ErrorLogger.debugLine("Parser closing "+token.toString());
            }
        } 
        else if(peekToken instanceof VariableToken)
        {
            // variables (e.g. aaa or b)
            retToken = (OperandToken)getNextToken(deliTyp);
       
            // check if the variable is followed by a dot operator
            if (peekNextToken(deliTyp) instanceof DotOperatorToken)
            {
                // e.g. a.something or a.sin() or a.getObject().getColor()
                operandStack.push(retToken);
                getNextToken(deliTyp);  // remove "." from scanner
                retToken = parseDotOperator(operandStack, deliTyp);
            }
            else if (peekNextToken(deliTyp) instanceof DelimiterToken)
            {
                // this might be something like e.g. ( sin (  )
                DelimiterToken token = ((DelimiterToken)peekNextToken(deliTyp));
                if (token.value == '(')
                {
                    ErrorLogger.debugLine("Parser: found function while parsing variable");
                    String name = ((VariableToken)peekToken).getName();
                    retToken = parseFunctionAndParameters( new FunctionToken(name), null );    
                }
                else if (token.value == '{')
                {
                    ErrorLogger.debugLine("Parser: found cell array structure");
                    String name = ((VariableToken)peekToken).getName();
                    retToken = parseFunctionAndParameters( new FunctionToken(name), null );    
                }
            }
            else
                ErrorLogger.debugLine("Parser: VariableToken: " + retToken.toString());
        }
        else if(peekToken instanceof FunctionToken)
        {
            // * / + - ' sin() cos() and more
            // something like sin() cos() somefunction() if() switch()
            String name = ((FunctionToken)getNextToken(deliTyp)).getName();

            /* if-then-else, while, for, switch */
            if( name.equals("if"))
            {
                ErrorLogger.debugLine("Parser: if");
        		retToken = parseIf();
                ErrorLogger.debugLine("Parser: if end");
            }
            else if( name.equals("while"))
            {
                ErrorLogger.debugLine("Parser: while");
                retToken = parseWhile();                    
                ErrorLogger.debugLine("Parser: while end");
            }
            else if( name.equals("for"))
            {
                ErrorLogger.debugLine("Parser: for");
                retToken = parseFor();                    
                ErrorLogger.debugLine("Parser: for end");
            }
            else if( name.equals("switch"))
            {
                ErrorLogger.debugLine("Parser: switch");
                retToken = parseSwitch();                    
                ErrorLogger.debugLine("Parser: switch end");
            }
            else
            {
                /* Some function */
                ErrorLogger.debugLine("Parser: function "+name);
                retToken = parseFunctionAndParameters( (FunctionToken)peekToken, null );                    
            }
        }
        else if(peekToken instanceof OperandToken)
        {
            // numbers, variables (e.g 3 or a or b)
            retToken = (OperandToken)getNextToken(deliTyp);
            ErrorLogger.debugLine("Parser: operand: " + retToken.toString());
        }
        else if(peekToken instanceof OperatorToken)
        { 
            Token nextToken = getNextToken(deliTyp);
            Token pToken    = peekNextToken(deliTyp);

⌨️ 快捷键说明

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