📄 parser.java
字号:
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 + -