📄 parser.java
字号:
// throw exception for multiple operands
// e.g. a=/7 a=*8 +*5 -*8 -/9
if (( (nextToken instanceof AssignmentOperatorToken) ||
(nextToken instanceof AddSubOperatorToken) ||
(nextToken instanceof MulDivOperatorToken) ) &&
(pToken instanceof MulDivOperatorToken) )
Errors.throwParserException("multiple operators * /");
// e.g. a=^7 +^3 -^6 *^5 ^^5 !^7
if (( (nextToken instanceof AssignmentOperatorToken) ||
(nextToken instanceof AddSubOperatorToken) ||
(nextToken instanceof PowerOperatorToken) ) &&
(pToken instanceof PowerOperatorToken) )
Errors.throwParserException("multiple operators ^");
ErrorLogger.debugLine("PARSER op+op: "+pToken);
ErrorLogger.debugLine("PARSER op+op: "+nextToken);
if(nextToken instanceof AssignmentOperatorToken)
{
ErrorLogger.debugLine("Parser: <x> = <y>");
retToken = parseAssignmentOperator(nextToken, operandStack);
}
else if(nextToken instanceof ColonOperatorToken)
{
ErrorLogger.debugLine("Parser: <x> : <y>");
retToken = parseColonOperator(nextToken, operandStack);
}
else if(nextToken instanceof DotOperatorToken)
{
ErrorLogger.debugLine("Parser: dot-operator");
retToken = parseDotOperator(operandStack, deliTyp);
}
else if( (nextToken instanceof AddSubOperatorToken)
|| (nextToken instanceof MulDivOperatorToken)
|| (nextToken instanceof PowerOperatorToken)
|| (nextToken instanceof BinaryOperatorToken)
|| (nextToken instanceof RelationOperatorToken))
{
/* Binary tokens: +, -, *, /, ^, <=, >=, ~=, == */
ErrorLogger.debugLine("Parser: <x> " + nextToken.toString() + " <y>");
retToken = parseBinaryOperator(nextToken, operandStack);
}
else if(nextToken instanceof UnaryOperatorToken)
{
ErrorLogger.debugLine("Parser: unary operator "+nextToken.toString());
retToken = parseUnaryOperator(nextToken, operandStack);
}
}
else
{
// every valid token must have been analyzed above
Errors.throwParserException(" unknown token: "+peekToken.toString());
}
ErrorLogger.decreaseIndent();
if (retToken!=null) ErrorLogger.debugLine("Parser return: " + retToken.toString());
else ErrorLogger.debugLine("Parser return: null");
return retToken;
} // end parseSingle
/**parse the expression contained in exp, this method is also called recursivly
to find the parameters of functions and matrices (e.g. something like 2+3+(2*4) )
@param deliTyp indicates if an argument is part of a matrix (whitespaces are treated
as delimiters in this case)
@return expression (e.g. 3 or 2+3 or sin(cos(3)) ) */
private OperandToken parseArithExpression(int deliTyp)
{
// expressions have their own stack
Stack operandStack = new Stack();
ErrorLogger.debugLine("Parser parseArithmeticExpr begin");
ErrorLogger.increaseIndent();
while(true)
{
// parsing is not useful if the next token will be a closing ")"
// (e.g. who() or a.getColor() )
if ( isExpectedDelimiter(peekNextToken(deliTyp), ')') )
break;
// parse next token
OperandToken subExpr = parseSingle(operandStack, deliTyp);
// Put parsed token on the operand stack
// If nothing useful was parsed then break
if (subExpr != null)
operandStack.push(subExpr);
Token peekToken = peekNextToken(deliTyp);
// arithmetic expressions are terminated by the following delimiters
if(peekToken instanceof DelimiterToken)
{
DelimiterToken token = ((DelimiterToken)peekToken);
// check wether or not the next token is a closing delimiter
if ( (token.value == ',') || (token.value == ';') ||
(token.value == '\r') || (token.value == '\n') ||
(token.value == '}') || (token.value == '-') ||
(token.value == ' ') || (token.value == ')') ||
(token.value == ']') )
{
ErrorLogger.debugLine("Parser delimiter break "+token.value);
break;
}
}
// if no more tokens are available return
if(peekToken==null)
break;
} // end while
// Check if the currently parsed expression is terminated by a delimiter
// which has the display property.
// (e.g: display "a=4," don't display "a=4;")
//if ((getCurrentToken() instanceof DelimiterToken) &&
// isDisplayResultToken(getCurrentToken()) &&
// !operandStack.isEmpty())
//{
// OperandToken op = (OperandToken)operandStack.pop();
// ErrorLogger.debugLine("Parser: display true "+op.toString());
// op.setDisplayResult(true);
// operandStack.push(op);
//}
// build return token
OperandToken retT = null;
if (!operandStack.isEmpty())
retT = (OperandToken)operandStack.pop();
// throw error if stacksize > 1
ErrorLogger.decreaseIndent();
ErrorLogger.debugLine("Parser parseArithmeticExpr end ");
return retT;
}
/** parse a list of commands (e.g. a=2+3;if(a=2){b=3};c=sin(pi) )
@return OperantToken tree of operand tokens (e.g. a=2+3) */
private OperandToken parseCommandList()
{
// these could be concatenated expressions (e.g.: "a=1;b=sin(4);c=3")
ErrorLogger.debugLine("Parser parseCommandList begin");
ErrorLogger.increaseIndent();
Stack operandStack = new Stack();
OperandToken command;
while (true)
{
// parse next token/command
ErrorLogger.debugLine("Parser parseCommandList next");
//command = parseSingle(operandStack, SINGLE);
// handling of {...} for commands is done here only, there has
// to be a difference in order to parse cell arrays
if (isExpectedDelimiter(peekNextToken(), '{' ))
{
getNextToken();
// get commands inside {...}
// get commands (e.g. if(3) ... endif or if(3) ... elseif
command = parseCommandList();
if (!isExpectedDelimiter( peekNextToken(), '}' ))
Errors.throwParserException(" parseCommandList ERROR missing }");
else
getNextToken();
}
else
command = parseSingle(operandStack, SINGLE);
Token peekToken = peekNextToken();
// Check if the currently parsed expression will be terminated by a delimiter
// which has the display property.
// (e.g: display "a=4," don't display "a=4;")
if (isDisplayResultToken(peekToken) && (command != null))
{
ErrorLogger.debugLine("Parser: display true "+command.toString());
command.setDisplayResult(true);
}
// put parsed token on the operand stack
if (command != null)
operandStack.push(command);
// Check if the token, why the parser is returned is correct
// Command lists are terminated by "}" "endif" "end" "else"
if ( isExpectedDelimiter(peekToken, "elseif") ||
isExpectedDelimiter(peekToken, "else") ||
isExpectedDelimiter(peekToken, "endif") ||
isExpectedDelimiter(peekToken, "end") ||
isExpectedDelimiter(peekToken, "endfunction") ||
isExpectedDelimiter(peekToken, "case") ||
isExpectedDelimiter(peekToken, "default") ||
isExpectedDelimiter(peekToken, "otherwise") ||
isExpectedDelimiter(peekToken, "endswitch") ||
isExpectedDelimiter(peekToken, "endwhile") ||
isExpectedDelimiter(peekToken, "endfor") ||
isExpectedDelimiter(peekToken, '}') )
{
// this path is only called from parseSingle( .. parseCommandList() )
ErrorLogger.debugLine("Parser parseCommandList break");
break;
}
else if (isExpectedDelimiter(peekToken, ',') ||
isExpectedDelimiter(peekToken, ';') ||
isExpectedDelimiter(peekToken, '\r') ||
isExpectedDelimiter(peekToken, '\n') )
{
// remove delimiters from parseSingle
getNextToken();
}
else if (peekToken == null)
{
// command lists may be terminated by end of file
break;
}
else
{
// is none of the above delimiters occured, there is an
// error e.g. ceil(5;8]
//Errors.throwParserException("parseCommandList wrong delimiter");
//break;
}
} // end while
// put all code parts from the stack into one expression object
OperandToken tree = null;
int stackSize = operandStack.size();
if (stackSize > 0)
{
//The expressions have been put onto the stack in reversed order
OperandToken[] opTokenArray = new OperandToken[stackSize];
for(int i=stackSize-1; i>=0; i--)
{
OperandToken ob = ((OperandToken)operandStack.pop());
opTokenArray[i] = ob;
}
tree = new Expression(null, opTokenArray, stackSize);
}
ErrorLogger.decreaseIndent();
ErrorLogger.debugLine("Parser parseCommandList end");
return tree;
}
/***************************************************************************************/
/***** individual parsing methods ******/
/***************************************************************************************/
/** parse <variable><=><operand> (e.g. a=3 or a=2+3+4 or [a,b]=step(x) ) */
/* @param */
/* @param */
/* @return expression of assignment (e.g. a=3) */
private OperandToken parseAssignmentOperator(Token currentToken, Stack operandStack)
{
// operator (this should be a "=")
OperatorToken operator = (OperatorToken)currentToken;
//parse right parameter
OperandToken rightSide = parseArithExpression(SINGLE);
//get left parameter from operandStack (e.g. a or [a,b,c] =...)
OperandToken leftSide = (OperandToken)operandStack.pop();
/* create new expression */
Expression tree = new Expression(operator, leftSide, rightSide);
return tree;
} // end parseAssignmentOperator
/***********************************************************************************/
/** parse <operand>:<operand> (e.g. 2:7 -> [2,3,4,5,6,7]) */
/** parse <operand>:<operand>:<operand> (e.g. 2:3:8 -> [2,5,8] */
/* @param */
/* @param */
/* @return */
private OperandToken parseColonOperator(Token nextToken, Stack operandStack)
{
OperandToken leftSide = null;
//get left parameter from operandStack
if(!operandStack.isEmpty())
leftSide =(OperandToken)operandStack.pop();
//parse right parameter
//be careful about e.g. a(:), a(1,:)
OperandToken rightSide = null;
if (!isExpectedDelimiter(peekNextToken(), ')') &&
!isExpectedDelimiter(peekNextToken(), ',') &&
!isExpectedDelimiter(peekNextToken(), ';') )
rightSide = parseArithExpression(SINGLE);
else
rightSide = null;
// also possible is something like a(1:end) or a(2:4:end)
if (isExpectedDelimiter(peekNextToken(), "end"))
rightSide = (OperandToken)getNextToken();
// Check is left Side is empty
if ((leftSide==null) ||
(leftSide instanceof DelimiterToken) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -