Skip to content

Commit

Permalink
corrected processing of error conditions in expression
Browse files Browse the repository at this point in the history
needed to catch command and operator tokens when an operand was expected
and return correct expected expression error

when checking token after operand, needed to specifically check for an
operator token type; was using isOperator(), which also returns true for
command tokens

when clearing hold stack of higher precedence operators, needed to allow
for tokens that don't have a table entry, both for precedence and is a
unary operator; replaced with precedence() that checks token instead of
the token code directly, and implemented new isUnaryOperator() that
takes a token instead of a token code

added more error tests for expression test #1 (note some of these tests
cause the older less robust translator expression mode to fail)
  • Loading branch information
thunder422 committed Jun 30, 2013
1 parent fab9d67 commit fc73988
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
7 changes: 7 additions & 0 deletions table.cpp
Expand Up @@ -1366,6 +1366,13 @@ CommandHandler Table::commandHandler(Code code) const
// TOKEN RELATED TABLE FUNCTIONS
//=================================

// returns whether the token contains a unary operator code
// (convenience function to avoid confusion)
bool Table::isUnaryOperator(Token *token) const
{
return token->hasTableEntry() ? isUnaryOperator(token->code()) : false;
}

// returns the precedence of the code contained in a token
//
// - the precedence is obtained from the token
Expand Down
1 change: 1 addition & 0 deletions table.h
Expand Up @@ -134,6 +134,7 @@ class Table
CommandHandler commandHandler(Code code) const;

// TOKEN RELATED TABLE FUNCTIONS
bool isUnaryOperator(Token *token) const;
int precedence(Token *token) const;
int flags(Token *token) const;
DataType expectedDataType(Token *token) const;
Expand Down
15 changes: 12 additions & 3 deletions test/expression1.dat
Expand Up @@ -15,10 +15,10 @@ A * B / C \ D MOD E
A mod B \ C / D * E
A * B ^ 2
a$ = "this" + "test"
# 2013-06-29: more tests
# more tests
-E
-45 + A
# 2013-06-30: data type tests
# data type tests
-A + B
-A + --B
A% + B
Expand All @@ -32,10 +32,19 @@ A% - B% * C
A% + B * C ^ D
A$ + B$
A$ < B$ = 0
# 2013-06-30: error tests
# mixed data type error tests
A$ + B
A$ + B%
A + B$
A% + B$
A$ - B$
-A$
# unexpected token type error tests
else
- else
- +
+
a print
a a
a + else
a + +
24 changes: 24 additions & 0 deletions test/expression1.txt
Expand Up @@ -101,3 +101,27 @@ Input: A$ - B$
Input: -A$
^^-- expected numeric expression

Input: else
^^^^-- expected expression

Input: - else
^^^^-- expected numeric expression

Input: - +
^-- expected numeric expression

Input: +
^-- expected expression

Input: a print
^^^^^-- expected operator or end-of-statement

Input: a a
^-- expected operator or end-of-statement

Input: a + else
^^^^-- expected numeric expression

Input: a + +
^-- expected numeric expression

7 changes: 6 additions & 1 deletion token.cpp
Expand Up @@ -118,8 +118,13 @@ void Token::initialize(void)
// set precedence for non-table token types
s_prec[Command_TokenType] = -1; // use table precedence if -1
s_prec[Operator_TokenType] = -1;
s_prec[IntFuncN_TokenType] = -1;
s_prec[IntFuncP_TokenType] = -1;
s_prec[DefFuncP_TokenType] = 2; // same as Paren_TokenType
// these tokens need to be lowest precedence but above Null_Code
s_prec[Constant_TokenType] = 2;
s_prec[DefFuncN_TokenType] = 2;
s_prec[DefFuncP_TokenType] = 2;
s_prec[NoParen_TokenType] = 2;
s_prec[Paren_TokenType] = 2;

// set token type has a table entry flags
Expand Down
16 changes: 9 additions & 7 deletions translator.cpp
Expand Up @@ -1583,7 +1583,9 @@ TokenStatus Translator::expectedErrStatus(DataType dataType)
ExpStrExpr_TokenStatus, // String
ExpStrExpr_TokenStatus, // SubStr
BUG_InvalidDataType, // numberof
ExpExpr_TokenStatus // None
ExpExpr_TokenStatus, // None
ExpNumExpr_TokenStatus, // Number
ExpExpr_TokenStatus // Any
};

return tokenStatus[dataType];
Expand Down Expand Up @@ -1888,8 +1890,7 @@ TokenStatus Translator::processOperator2(Token *&token)
{
// unary operators don't force other tokens from hold stack
while (m_table.precedence(m_holdStack.top().token)
>= m_table.precedence(token->code())
&& !m_table.isUnaryOperator(token->code()))
>= m_table.precedence(token) && !m_table.isUnaryOperator(token))
{
// pop operator on top of stack and add it to the output
Token *topToken = m_holdStack.top().token;
Expand Down Expand Up @@ -1918,7 +1919,8 @@ TokenStatus Translator::processOperator2(Token *&token)
}

// check for end of expression
if (!token->isOperator() || m_table.flags(token) & EndExpr_Flag)
if (!token->isType(Operator_TokenType)
|| m_table.flags(token) & EndExpr_Flag)
{
return Done_TokenStatus;
}
Expand Down Expand Up @@ -1955,9 +1957,9 @@ TokenStatus Translator::getOperand(Token *&token, DataType dataType)

switch (token->type())
{
//case Command_TokenType:
//case Operator_TokenType:
// TODO return expected X expresssion here from dataType
case Command_TokenType:
case Operator_TokenType:
return expectedErrStatus(dataType);

case Constant_TokenType:
// fall thru
Expand Down

0 comments on commit fc73988

Please sign in to comment.