diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 1b5e36b6d..1268f602b 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -4,34 +4,51 @@ #include #include "generator.hpp" +#include "scanner.hpp" +#include "errorhandler.hpp" namespace Compiler { ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals) - : Parser (errorHandler, context), mLocals (locals), mLiterals (literals) + : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), + mNextOperand (true) {} bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) { - Operand operand; - operand.mType = 'l'; - operand.mInteger = value; + if (mNextOperand) + { + Operand operand; + operand.mType = 'l'; + operand.mInteger = value; - mOperands.push_back (operand); + mOperands.push_back (operand); + + mNextOperand = false; + mTokenLoc = loc; + return true; + } - return false; + return Parser::parseInt (value, loc, scanner); } bool ExprParser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner) { - Operand operand; - operand.mType = 'f'; - operand.mFloat = value; + if (mNextOperand) + { + Operand operand; + operand.mType = 'f'; + operand.mFloat = value; - mOperands.push_back (operand); + mOperands.push_back (operand); + + mNextOperand = false; + mTokenLoc = loc; + return true; + } - return false; + return Parser::parseFloat (value, loc, scanner); } bool ExprParser::parseName (const std::string& name, const TokenLoc& loc, @@ -47,19 +64,39 @@ namespace Compiler bool ExprParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) { + if (code==Scanner::S_comma) + { + // end marker + mTokenLoc = loc; + return false; + } + + if (code==Scanner::S_newline) + { + // end marker + mTokenLoc = loc; + scanner.putbackNewline (loc); + return false; + } + return Parser::parseSpecial (code, loc, scanner); } void ExprParser::reset() { mOperands.clear(); + mOperators.clear(); + mNextOperand = true; } char ExprParser::write (std::vector& code) { - if (mOperands.empty()) - throw std::logic_error ("empty expression"); + if (mOperands.empty() && mOperators.empty()) + getErrorHandler().error ("missing expression", mTokenLoc); + if (mNextOperand) + getErrorHandler().error ("syntax error in expression", mTokenLoc); + Operand operand = mOperands[mOperands.size()-1]; mOperands.clear(); diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 5f58930f4..0370e35e2 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -6,6 +6,7 @@ #include #include "parser.hpp" +#include "tokenloc.hpp" namespace Compiler { @@ -24,6 +25,9 @@ namespace Compiler Locals& mLocals; Literals& mLiterals; std::vector mOperands; + std::vector mOperators; + bool mNextOperand; + TokenLoc mTokenLoc; public: diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index a202eca5c..17b2dc305 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -43,6 +43,12 @@ namespace Compiler bool Scanner::scanToken (Parser& parser) { + if (mNewline) + { + mNewline = false; + return parser.parseSpecial (S_newline, mPutbackLoc, *this); + } + char c; if (!get (c)) @@ -412,13 +418,20 @@ namespace Compiler // constructor Scanner::Scanner (ErrorHandler& errorHandler, std::istream& inputStream) - : mErrorHandler (errorHandler), mStream (inputStream) + : mErrorHandler (errorHandler), mStream (inputStream), mNewline (false) { } void Scanner::scan (Parser& parser) { + mNewline = false; while (scanToken (parser)); } + + void Scanner::putbackNewline (const TokenLoc& loc) + { + mNewline = true; + mPutbackLoc = loc; + } } diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index 1349a976a..63a0dbb4d 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -22,6 +22,8 @@ namespace Compiler TokenLoc mLoc; TokenLoc mPrevLoc; std::istream& mStream; + bool mNewline; + TokenLoc mPutbackLoc; public: @@ -78,6 +80,9 @@ namespace Compiler void scan (Parser& parser); ///< Scan a token and deliver it to the parser. + + void putbackNewline (const TokenLoc& loc); + ///< put back a newline token }; }