implemented optional arguments

actorid
Marc Zinnschlag 15 years ago
parent 17135a6403
commit f4e79a48f0

@ -17,21 +17,21 @@ namespace Compiler
{
std::pair<Codes, Codes> entry;
if (mState!=IfElseBodyState)
if (mState!=IfElseBodyState)
mExprParser.append (entry.first);
std::copy (mCodeBlock.begin(), mCodeBlock.end(),
std::back_inserter (entry.second));
mIfCode.push_back (entry);
mCodeBlock.clear();
if (keyword==Scanner::K_endif)
{
// store code for if-cascade
Codes codes;
for (IfCodes::reverse_iterator iter (mIfCode.rbegin());
iter!=mIfCode.rend(); ++iter)
{
@ -47,17 +47,17 @@ namespace Compiler
std::back_inserter (block));
Generator::jumpOnZero (block, iter->second.size()+1);
}
std::copy (iter->second.begin(), iter->second.end(),
std::back_inserter (block));
std::swap (codes, block);
std::copy (block.begin(), block.end(), std::back_inserter (codes));
}
std::copy (codes.begin(), codes.end(), std::back_inserter (mCode));
mIfCode.clear();
mState = IfEndifState;
}
@ -66,36 +66,36 @@ namespace Compiler
mExprParser.reset();
scanner.scan (mExprParser);
mState = IfElseifEndState;
mState = IfElseifEndState;
}
else if (keyword==Scanner::K_else)
{
mState = IfElseEndState;
}
mState = IfElseEndState;
}
return true;
}
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
{
// nested
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
if (parser.parseKeyword (keyword, loc, scanner))
scanner.scan (parser);
parser.appendCode (mCodeBlock);
scanner.scan (parser);
parser.appendCode (mCodeBlock);
return true;
}
else
{
mLineParser.reset();
if (mLineParser.parseKeyword (keyword, loc, scanner))
scanner.scan (mLineParser);
return true;
}
scanner.scan (mLineParser);
return true;
}
return false;
}
@ -104,24 +104,24 @@ namespace Compiler
if (keyword==Scanner::K_endwhile)
{
Codes loop;
Codes expr;
mExprParser.append (expr);
Generator::jump (loop, -mCodeBlock.size()-expr.size());
std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
Codes skip;
Generator::jumpOnZero (skip, mCodeBlock.size()+loop.size()+1);
std::copy (skip.begin(), skip.end(), std::back_inserter (mCode));
std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (mCode));
Codes loop2;
Generator::jump (loop2, -mCodeBlock.size()-expr.size()-skip.size());
if (loop.size()!=loop2.size())
@ -129,31 +129,31 @@ namespace Compiler
"internal compiler error: failed to generate a while loop");
std::copy (loop2.begin(), loop2.end(), std::back_inserter (mCode));
mState = WhileEndwhileState;
return true;
return true;
}
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
{
// nested
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
if (parser.parseKeyword (keyword, loc, scanner))
scanner.scan (parser);
parser.appendCode (mCodeBlock);
scanner.scan (parser);
parser.appendCode (mCodeBlock);
return true;
}
else
{
mLineParser.reset();
if (mLineParser.parseKeyword (keyword, loc, scanner))
scanner.scan (mLineParser);
return true;
}
scanner.scan (mLineParser);
return true;
}
return false;
}
@ -164,14 +164,14 @@ namespace Compiler
mExprParser (errorHandler, context, locals, literals),
mState (StartState)
{
}
void ControlParser::appendCode (std::vector<Interpreter::Type_Code>& code) const
{
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
}
bool ControlParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
{
if (mState==StartState)
@ -190,20 +190,20 @@ namespace Compiler
scanner.scan (mExprParser);
mState = WhileEndState;
return true;
return true;
}
}
else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState)
{
if (parseIfBody (keyword, loc, scanner))
return true;
return true;
}
else if (mState==WhileBodyState)
{
if ( parseWhileBody (keyword, loc, scanner))
return true;
}
return Parser::parseKeyword (keyword, loc, scanner);
}
@ -218,24 +218,24 @@ namespace Compiler
case IfElseEndState: mState = IfElseBodyState; return true;
case WhileEndState: mState = WhileBodyState; return true;
case IfBodyState:
case IfElseifBodyState:
case IfElseBodyState:
case WhileBodyState:
return true; // empty line
case IfEndifState:
case WhileEndwhileState:
return false;
default: ;
}
}
return Parser::parseSpecial (code, loc, scanner);
}
@ -245,6 +245,6 @@ namespace Compiler
mCodeBlock.clear();
mIfCode.clear();
mState = StartState;
Parser::reset();
}
}

@ -22,33 +22,33 @@ namespace Compiler
switch (op)
{
case '(':
return 0;
case 'e': // ==
case 'n': // !=
case 'l': // <
case 'L': // <=
case 'g': // <
case 'G': // >=
return 1;
case '+':
case '-':
return 2;
case '*':
case '/':
return 3;
case 'm':
return 4;
}
return 0;
}
@ -59,7 +59,7 @@ namespace Compiler
assert (Index<static_cast<int> (mOperands.size()));
return mOperands[mOperands.size()-1-Index];
}
char ExprParser::getOperator() const
{
assert (!mOperators.empty());
@ -70,27 +70,27 @@ namespace Compiler
{
return std::find (mOperators.begin(), mOperators.end(), '(')!=mOperators.end();
}
void ExprParser::popOperator()
{
assert (!mOperators.empty());
mOperators.resize (mOperators.size()-1);
mOperators.resize (mOperators.size()-1);
}
void ExprParser::popOperand()
{
assert (!mOperands.empty());
mOperands.resize (mOperands.size()-1);
mOperands.resize (mOperands.size()-1);
}
void ExprParser::replaceBinaryOperands()
{
char t1 = getOperandType (1);
char t2 = getOperandType();
popOperand();
popOperand();
if (t1==t2)
mOperands.push_back (t1);
else if (t1=='f' || t2=='f')
@ -102,59 +102,59 @@ namespace Compiler
void ExprParser::pop()
{
char op = getOperator();
switch (op)
{
case 'm':
Generator::negate (mCode, getOperandType());
popOperator();
break;
case '+':
Generator::add (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case '-':
Generator::sub (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case '*':
Generator::mul (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
break;
case '/':
Generator::div (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case 'e':
case 'n':
case 'l':
case 'L':
case 'g':
case 'G':
Generator::compare (mCode, op, getOperandType (1), getOperandType());
popOperator();
popOperand();
popOperand();
mOperands.push_back ('l');
break;
default:
throw std::logic_error ("unknown operator");
}
}
@ -165,36 +165,36 @@ namespace Compiler
mOperands.push_back ('l');
Generator::pushInt (mCode, mLiterals, value);
}
void ExprParser::pushFloatLiteral (float value)
{
mNextOperand = false;
mOperands.push_back ('f');
Generator::pushFloat (mCode, mLiterals, value);
Generator::pushFloat (mCode, mLiterals, value);
}
void ExprParser::pushBinaryOperator (char c)
{
while (!mOperators.empty() && getPriority (getOperator())>=getPriority (c))
pop();
mOperators.push_back (c);
mNextOperand = true;
}
void ExprParser::close()
{
while (getOperator()!='(')
pop();
popOperator();
}
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
{
parseArguments (arguments, scanner, mCode);
return parseArguments (arguments, scanner, mCode);
}
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals, bool argument)
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
@ -205,11 +205,13 @@ namespace Compiler
{
if (!mExplicit.empty())
return Parser::parseInt (value, loc, scanner);
mFirst = false;
if (mNextOperand)
{
{
start();
pushIntegerLiteral (value);
mTokenLoc = loc;
return true;
@ -228,13 +230,15 @@ namespace Compiler
return Parser::parseFloat (value, loc, scanner);
mFirst = false;
if (mNextOperand)
{
{
start();
pushFloatLiteral (value);
mTokenLoc = loc;
return true;
}
}
else
{
// no comma was used between arguments
@ -252,29 +256,31 @@ namespace Compiler
mFirst = false;
if (mNextOperand)
{
{
start();
std::string name2 = toLower (name);
char type = mLocals.getType (name2);
if (type!=' ')
{
Generator::fetchLocal (mCode, type, mLocals.getIndex (name2));
mNextOperand = false;
mOperands.push_back (type=='f' ? 'f' : 'l');
return true;
mOperands.push_back (type=='f' ? 'f' : 'l');
return true;
}
type = getContext().getGlobalType (name2);
if (type!=' ')
{
Generator::fetchGlobal (mCode, mLiterals, type, name2);
mNextOperand = false;
mOperands.push_back (type=='f' ? 'f' : 'l');
return true;
mOperands.push_back (type=='f' ? 'f' : 'l');
return true;
}
if (mExplicit.empty() && getContext().isId (name))
{
mExplicit = name;
@ -287,161 +293,183 @@ namespace Compiler
scanner.putbackName (name, loc);
return false;
}
return Parser::parseName (name, loc, scanner);
}
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
{
mFirst = false;
if (!mExplicit.empty())
{
if (mRefOp && mNextOperand)
{
if (keyword==Scanner::K_getdisabled)
{
mTokenLoc = loc;
start();
mTokenLoc = loc;
Generator::getDisabled (mCode, mLiterals, mExplicit);
mOperands.push_back ('l');
mExplicit.clear();
mRefOp = false;
mNextOperand = false;
return true;
}
return true;
}
else if (keyword==Scanner::K_getdistance)
{
start();
mTokenLoc = loc;
parseArguments ("c", scanner);
Generator::getDistance (mCode, mLiterals, mExplicit);
mOperands.push_back ('f');
mExplicit.clear();
mRefOp = false;
mNextOperand = false;
return true;
}
}
// check for custom extensions
if (const Extensions *extensions = getContext().getExtensions())
{
char returnType;
std::string argumentType;
if (extensions->isFunction (keyword, returnType, argumentType, true))
{
start();
mTokenLoc = loc;
parseArguments (argumentType, scanner);
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit);
mOperands.push_back (returnType);
mExplicit.clear();
mRefOp = false;
mNextOperand = false;
return true;
}
}
}
return Parser::parseKeyword (keyword, loc, scanner);
}
if (mNextOperand)
{
{
if (keyword==Scanner::K_getsquareroot)
{
mTokenLoc = loc;
start();
mTokenLoc = loc;
parseArguments ("f", scanner);
Generator::squareRoot (mCode);
mOperands.push_back ('f');
mNextOperand = false;
return true;
}
else if (keyword==Scanner::K_menumode)
{
start();
mTokenLoc = loc;
Generator::menuMode (mCode);
mOperands.push_back ('l');
mNextOperand = false;
return true;
}
else if (keyword==Scanner::K_random)
{
mTokenLoc = loc;
start();
mTokenLoc = loc;
parseArguments ("l", scanner);
Generator::random (mCode);
mOperands.push_back ('l');
mNextOperand = false;
return true;
return true;
}
else if (keyword==Scanner::K_scriptrunning)
{
start();
mTokenLoc = loc;
parseArguments ("c", scanner);
Generator::scriptRunning (mCode);
mOperands.push_back ('l');
mNextOperand = false;
return true;
}
}
else if (keyword==Scanner::K_getdistance)
{
start();
mTokenLoc = loc;
parseArguments ("c", scanner);
Generator::getDistance (mCode, mLiterals, "");
mOperands.push_back ('f');
mNextOperand = false;
return true;
}
}
else if (keyword==Scanner::K_getsecondspassed)
{
mTokenLoc = loc;
start();
mTokenLoc = loc;
Generator::getSecondsPassed (mCode);
mOperands.push_back ('f');
mNextOperand = false;
return true;
return true;
}
else if (keyword==Scanner::K_getdisabled)
{
mTokenLoc = loc;
start();
mTokenLoc = loc;
Generator::getDisabled (mCode, mLiterals, "");
mOperands.push_back ('l');
mNextOperand = false;
return true;
return true;
}
else
{
// check for custom extensions
if (const Extensions *extensions = getContext().getExtensions())
{
start();
char returnType;
std::string argumentType;
if (extensions->isFunction (keyword, returnType, argumentType, false))
{
mTokenLoc = loc;
parseArguments (argumentType, scanner);
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
mOperands.push_back (returnType);
mNextOperand = false;
return true;
}
@ -454,7 +482,7 @@ namespace Compiler
scanner.putbackKeyword (keyword, loc);
return false;
}
return Parser::parseKeyword (keyword, loc, scanner);
}
@ -467,10 +495,10 @@ namespace Compiler
mRefOp = true;
return true;
}
return Parser::parseSpecial (code, loc, scanner);
}
if (code==Scanner::S_comma)
{
mTokenLoc = loc;
@ -481,14 +509,14 @@ namespace Compiler
mFirst = false;
return true;
}
// end marker
scanner.putbackSpecial (code, loc);
return false;
}
mFirst = false;
if (code==Scanner::S_newline)
{
// end marker
@ -496,7 +524,7 @@ namespace Compiler
scanner.putbackSpecial (code, loc);
return false;
}
if (code==Scanner::S_minus && mNextOperand)
{
// unary
@ -504,7 +532,7 @@ namespace Compiler
mTokenLoc = loc;
return true;
}
if (code==Scanner::S_open)
{
if (mNextOperand)
@ -520,7 +548,7 @@ namespace Compiler
return false;
}
}
if (code==Scanner::S_close && !mNextOperand)
{
if (isOpen())
@ -528,17 +556,17 @@ namespace Compiler
close();
return true;
}
mTokenLoc = loc;
scanner.putbackSpecial (code, loc);
return false;
}
if (!mNextOperand)
{
mTokenLoc = loc;
char c = 0; // comparison
switch (code)
{
case Scanner::S_plus: pushBinaryOperator ('+'); return true;
@ -552,7 +580,7 @@ namespace Compiler
case Scanner::S_cmpGT: c = 'g'; break;
case Scanner::S_cmpGE: c = 'G'; break;
}
if (c)
{
if (mArgument && !isOpen())
@ -562,15 +590,15 @@ namespace Compiler
scanner.putbackSpecial (code, loc);
return false;
}
pushBinaryOperator (c);
return true;
}
}
return Parser::parseSpecial (code, loc, scanner);
}
void ExprParser::reset()
{
mOperands.clear();
@ -580,8 +608,9 @@ namespace Compiler
mFirst = true;
mExplicit.clear();
mRefOp = false;
Parser::reset();
}
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
{
if (mOperands.empty() && mOperators.empty())
@ -589,7 +618,7 @@ namespace Compiler
getErrorHandler().error ("missing expression", mTokenLoc);
return 'l';
}
if (mNextOperand || mOperands.empty())
{
getErrorHandler().error ("syntax error in expression", mTokenLoc);
@ -603,62 +632,90 @@ namespace Compiler
assert (mOperands.size()==1);
return mOperands[0];
}
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
}
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
std::vector<Interpreter::Type_Code>& code, bool invert)
{
bool optional = false;
bool optionalCount = 0;
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
std::stack<std::vector<Interpreter::Type_Code> > stack;
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
++iter)
{
if (*iter=='S' || *iter=='c')
if (*iter=='/')
{
optional = true;
}
else if (*iter=='S' || *iter=='c')
{
stringParser.reset();
if (optional)
stringParser.setOptional (true);
if (*iter=='c') stringParser.smashCase();
scanner.scan (stringParser);
scanner.scan (stringParser);
if (optional && stringParser.isEmpty())
break;
if (invert)
{
std::vector<Interpreter::Type_Code> tmp;
stringParser.append (tmp);
stack.push (tmp);
}
else
stringParser.append (code);
if (optional)
++optionalCount;
}
else
{
parser.reset();
parser.reset();
if (optional)
parser.setOptional (true);
scanner.scan (parser);
if (optional && parser.isEmpty())
break;
std::vector<Interpreter::Type_Code> tmp;
char type = parser.append (tmp);
if (type!=*iter)
Generator::convert (tmp, type, *iter);
if (invert)
stack.push (tmp);
else
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
if (optional)
++optionalCount;
}
}
while (!stack.empty())
{
std::vector<Interpreter::Type_Code>& tmp = stack.top();
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
stack.pop();
}
}
}
return optionalCount;
}
}

@ -15,7 +15,7 @@ namespace Compiler
class ExprParser : public Parser
{
Locals& mLocals;
Locals& mLocals;
Literals& mLiterals;
std::vector<char> mOperands;
std::vector<char> mOperators;
@ -26,35 +26,35 @@ namespace Compiler
bool mArgument;
std::string mExplicit;
bool mRefOp;
int getPriority (char op) const;
char getOperandType (int Index = 0) const;
char getOperandType (int Index = 0) const;
char getOperator() const;
bool isOpen() const;
void popOperator();
void popOperand();
void replaceBinaryOperands();
void pop();
void pushIntegerLiteral (int value);
void pushFloatLiteral (float value);
void pushBinaryOperator (char c);
void close();
void parseArguments (const std::string& arguments, Scanner& scanner);
int parseArguments (const std::string& arguments, Scanner& scanner);
public:
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals, bool argument = false);
///< constructor
@ -84,20 +84,22 @@ namespace Compiler
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
///< Handle a special character token.
/// \return fetch another token?
void reset();
///< Reset parser to clean state.
char append (std::vector<Interpreter::Type_Code>& code);
///< Generate code for parsed expression.
/// \return Type ('l': integer, 'f': float)
void parseArguments (const std::string& arguments, Scanner& scanner,
int parseArguments (const std::string& arguments, Scanner& scanner,
std::vector<Interpreter::Type_Code>& code, bool invert = false);
///< Parse sequence of arguments specified by \a arguments.
/// \param arguments Each character represents one arguments ('l': integer,
/// 'f': float, 'S': string, 'c': string (case smashed))
/// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
/// optional)
/// \param invert Store arguments in reverted order.
/// \return number of optional arguments
};
}

@ -8,7 +8,7 @@
namespace Compiler
{
FileParser::FileParser (ErrorHandler& errorHandler, Context& context)
: Parser (errorHandler, context),
: Parser (errorHandler, context),
mScriptParser (errorHandler, context, mLocals, true),
mState (BeginState)
{}
@ -17,12 +17,12 @@ namespace Compiler
{
return mName;
}
void FileParser::getCode (std::vector<Interpreter::Type_Code>& code) const
{
mScriptParser.getCode (code);
}
const Locals& FileParser::getLocals() const
{
return mLocals;
@ -37,17 +37,17 @@ namespace Compiler
mState = BeginCompleteState;
return true;
}
if (mState==EndNameState)
{
// optional repeated name after end statement
if (mName!=name)
reportWarning ("Names for script " + mName + " do not match", loc);
mState = EndCompleteState;
return true;
}
return Parser::parseName (name, loc, scanner);
}
@ -58,7 +58,7 @@ namespace Compiler
mState = NameState;
return true;
}
if (mState==NameState)
{
// keywords can be used as script names too. Thank you Morrowind for another
@ -67,7 +67,7 @@ namespace Compiler
mState = BeginCompleteState;
return true;
}
return Parser::parseKeyword (keyword, loc, scanner);
}
@ -80,25 +80,25 @@ namespace Compiler
// ignore empty lines
return true;
}
if (mState==BeginCompleteState)
{
// parse the script body
mScriptParser.reset();
scanner.scan (mScriptParser);
mState = EndNameState;
return true;
}
if (mState==EndCompleteState || mState==EndNameState)
{
// we are done here -> ignore the rest of the script
return false;
}
}
return Parser::parseSpecial (code, loc, scanner);
}
@ -107,12 +107,12 @@ namespace Compiler
if (mState!=EndNameState && mState!=EndCompleteState)
Parser::parseEOF (scanner);
}
void FileParser::reset()
{
mState = BeginState;
mName.clear();
mScriptParser.reset();
Parser::reset();
}
}

@ -57,15 +57,15 @@ namespace Compiler
std::string Parser::toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
Parser::Parser (ErrorHandler& errorHandler, Context& context)
: mErrorHandler (errorHandler), mContext (context)
: mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
{}
// destructor
@ -79,7 +79,9 @@ namespace Compiler
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
{
reportSeriousError ("Unexpected numeric value", loc);
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected numeric value", loc);
return false;
}
@ -90,7 +92,9 @@ namespace Compiler
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
{
reportSeriousError ("Unexpected floating point value", loc);
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected floating point value", loc);
return false;
}
@ -102,7 +106,9 @@ namespace Compiler
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
Scanner& scanner)
{
reportSeriousError ("Unexpected name", loc);
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected name", loc);
return false;
}
@ -113,7 +119,9 @@ namespace Compiler
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
{
reportSeriousError ("Unexpected keyword", loc);
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected keyword", loc);
return false;
}
@ -124,7 +132,9 @@ namespace Compiler
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
{
reportSeriousError ("Unexpected special token", loc);
if (!(mOptional && mEmpty))
reportSeriousError ("Unexpected special token", loc);
return false;
}
@ -136,5 +146,25 @@ namespace Compiler
{
reportEOF();
}
}
void Parser::reset()
{
mOptional = false;
mEmpty = true;
}
void Parser::setOptional (bool optional)
{
mOptional = optional;
}
void Parser::start()
{
mEmpty = false;
}
bool Parser::isEmpty() const
{
return mEmpty;
}
}

@ -18,6 +18,8 @@ namespace Compiler
{
ErrorHandler& mErrorHandler;
Context& mContext;
bool mOptional;
bool mEmpty;
protected:
@ -47,7 +49,7 @@ namespace Compiler
///< constructor
virtual ~Parser();
///< destructor
///< destructor
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
///< Handle an int token.
@ -84,6 +86,19 @@ namespace Compiler
///< Handle EOF token.
///
/// - Default-implementation: Report an error.
virtual void reset();
///< Reset parser to clean state.
void setOptional (bool optional);
///< Optional mode: If nothign has been parsed yet and an unexpected token is delivered, stop
/// parsing without raising an exception (after a reset the parser is in non-optional mode).
void start();
///< Mark parser as non-empty (at least one token has been parser).
bool isEmpty() const;
///< Has anything been parsed?
};
}

@ -12,7 +12,7 @@ namespace Compiler
StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals)
: Parser (errorHandler, context), mLiterals (literals), mState (StartState), mSmashCase (false)
{
}
bool StringParser::parseName (const std::string& name, const TokenLoc& loc,
@ -20,14 +20,15 @@ namespace Compiler
{
if (mState==StartState || mState==CommaState)
{
start();
if (mSmashCase)
Generator::pushString (mCode, mLiterals, toLower (name));
else
Generator::pushString (mCode, mLiterals, toLower (name));
else
Generator::pushString (mCode, mLiterals, name);
return false;
}
return Parser::parseName (name, loc, scanner);
}
@ -38,10 +39,10 @@ namespace Compiler
mState = CommaState;
return true;
}
return Parser::parseSpecial (code, loc, scanner);
}
void StringParser::append (std::vector<Interpreter::Type_Code>& code)
{
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
@ -52,11 +53,11 @@ namespace Compiler
mState = StartState;
mCode.clear();
mSmashCase = false;
Parser::reset();
}
void StringParser::smashCase()
{
mSmashCase = true;
}
}

Loading…
Cancel
Save