diff --git a/components/compiler/controlparser.cpp b/components/compiler/controlparser.cpp index 4715d3214..2f5d5c4b6 100644 --- a/components/compiler/controlparser.cpp +++ b/components/compiler/controlparser.cpp @@ -17,21 +17,21 @@ namespace Compiler { std::pair 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& 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(); } } - diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index d0138078e..484aea878 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -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 (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& 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& code, bool invert) { + bool optional = false; + bool optionalCount = 0; + ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true); StringParser stringParser (getErrorHandler(), getContext(), mLiterals); - + std::stack > 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 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 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& tmp = stack.top(); - + std::copy (tmp.begin(), tmp.end(), std::back_inserter (code)); - + stack.pop(); } - } -} + return optionalCount; + } +} diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 0dd8c871a..87945c628 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -15,7 +15,7 @@ namespace Compiler class ExprParser : public Parser { - Locals& mLocals; + Locals& mLocals; Literals& mLiterals; std::vector mOperands; std::vector 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& 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& 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 }; } diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 6e26f48d6..9b184f1ff 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -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& 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(); } } - diff --git a/components/compiler/parser.cpp b/components/compiler/parser.cpp index ff5bf33ee..73cadfeba 100644 --- a/components/compiler/parser.cpp +++ b/components/compiler/parser.cpp @@ -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; + } +} diff --git a/components/compiler/parser.hpp b/components/compiler/parser.hpp index a55f5a024..221e7c2c9 100644 --- a/components/compiler/parser.hpp +++ b/components/compiler/parser.hpp @@ -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? }; } diff --git a/components/compiler/stringparser.cpp b/components/compiler/stringparser.cpp index 633b7eab4..396a88c78 100644 --- a/components/compiler/stringparser.cpp +++ b/components/compiler/stringparser.cpp @@ -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& 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; } } -