diff options
Diffstat (limited to 'lib/Parser')
| -rw-r--r-- | lib/Parser/Parser.cc | 2 | ||||
| -rw-r--r-- | lib/Parser/ParserControlFlow.cc | 12 | ||||
| -rw-r--r-- | lib/Parser/ParserExpression.cc | 42 | ||||
| -rw-r--r-- | lib/Parser/ParserFunction.cc | 6 | ||||
| -rw-r--r-- | lib/Parser/ParserType.cc | 27 |
5 files changed, 63 insertions, 26 deletions
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index d8fecdc..f2fcbc8 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -86,7 +86,9 @@ std::vector<std::unique_ptr<StmtAST>> Parser::ParseBlock(std::initializer_list<i } std::unique_ptr<StmtAST> Parser::ParseStatement() { + int Line = Lex.getLine(); auto Stmt = ParseStatementImpl(); + if (Stmt && !Stmt->getLine()) Stmt->setLine(Line); if (!Stmt) ++NumErrors; return Stmt; } diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc index d01e561..afa8bd8 100644 --- a/lib/Parser/ParserControlFlow.cc +++ b/lib/Parser/ParserControlFlow.cc @@ -27,7 +27,7 @@ std::unique_ptr<StmtAST> Parser::ParseIfStmt() { if (!Cond) return nullptr; if (CurTok != tok_then) { - fprintf(stderr, "error: expected THEN\n"); + fprintf(stderr, "error: expected THEN at line %d\n", Lex.getLine()); return nullptr; } getNextToken(); @@ -41,7 +41,7 @@ std::unique_ptr<StmtAST> Parser::ParseIfStmt() { } if (CurTok != tok_endif) { - fprintf(stderr, "error: expected ENDIF\n"); + fprintf(stderr, "error: expected ENDIF at line %d\n", Lex.getLine()); return nullptr; } getNextToken(); @@ -54,12 +54,6 @@ std::unique_ptr<StmtAST> Parser::ParseWhileStmt() { auto Cond = ParseExpression(); if (!Cond) return nullptr; - if (CurTok != tok_do) { - fprintf(stderr, "error: expected DO after WHILE condition\n"); - return nullptr; - } - getNextToken(); - std::vector<std::unique_ptr<StmtAST>> Body = ParseBlock({tok_endwhile}); if (CurTok != tok_endwhile) { @@ -135,7 +129,7 @@ std::unique_ptr<StmtAST> Parser::ParseForStmt() { return nullptr; } - if (Lex.IdentifierStr != VarName) { + if (!sameIdentifier(Lex.IdentifierStr, VarName)) { fprintf(stderr, "error: NEXT identifier '%s' does not match FOR variable '%s'\n", Lex.IdentifierStr.c_str(), VarName.c_str()); return nullptr; diff --git a/lib/Parser/ParserExpression.cc b/lib/Parser/ParserExpression.cc index d32c407..b8952a8 100644 --- a/lib/Parser/ParserExpression.cc +++ b/lib/Parser/ParserExpression.cc @@ -1,6 +1,7 @@ #include "cps/Parser.h" #include "cps/FunctionAST.h" #include <cstdio> +#include <limits> using namespace cps; @@ -13,15 +14,29 @@ int Parser::GetTokPrecedence() { } +bool Parser::ParseIntegerValue(bool Negative, int64_t &Out) { + const uint64_t Max = uint64_t(std::numeric_limits<int64_t>::max()); + if (Lex.NumVal > Max + (Negative ? 1u : 0u)) { + fprintf(stderr, "error: Integer literal is outside the i64 range at line %d\n", Lex.getLine()); + getNextToken(); + return false; + } + Out = Negative && Lex.NumVal == Max + 1 + ? std::numeric_limits<int64_t>::min() + : Negative ? -static_cast<int64_t>(Lex.NumVal) : static_cast<int64_t>(Lex.NumVal); + getNextToken(); + return true; +} + std::unique_ptr<ExprAST> Parser::ParseNumberExpr() { if (CurTok == tok_number_real) { auto Result = std::make_unique<RealExprAST>(Lex.RealVal); getNextToken(); return Result; } - auto Result = std::make_unique<IntegerExprAST>(Lex.NumVal); - getNextToken(); - return Result; + int64_t Value; + if (!ParseIntegerValue(false, Value)) return nullptr; + return std::make_unique<IntegerExprAST>(Value); } std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() { @@ -109,7 +124,7 @@ std::unique_ptr<ExprAST> Parser::ParseParenExpr() { auto V = ParseExpression(); if (!V) return nullptr; if (CurTok != ')') { - fprintf(stderr, "error: expected ')'\n"); + fprintf(stderr, "error: expected ')' at line %d\n", Lex.getLine()); return nullptr; } getNextToken(); @@ -117,6 +132,13 @@ std::unique_ptr<ExprAST> Parser::ParseParenExpr() { } std::unique_ptr<ExprAST> Parser::ParsePrimary() { + int Line = Lex.getLine(); + auto Expr = ParsePrimaryImpl(); + if (Expr && !Expr->getLine()) Expr->setLine(Line); + return Expr; +} + +std::unique_ptr<ExprAST> Parser::ParsePrimaryImpl() { switch (CurTok) { case tok_identifier: return ParseIdentifierExpr(); case tok_number_int: return ParseNumberExpr(); @@ -148,6 +170,13 @@ std::unique_ptr<ExprAST> Parser::ParsePrimary() { } std::unique_ptr<ExprAST> Parser::ParseUnary() { + int Line = Lex.getLine(); + auto Expr = ParseUnaryImpl(); + if (Expr && !Expr->getLine()) Expr->setLine(Line); + return Expr; +} + +std::unique_ptr<ExprAST> Parser::ParseUnaryImpl() { if (CurTok == tok_not) { getNextToken(); auto Operand = ParseUnary(); @@ -178,6 +207,11 @@ std::unique_ptr<ExprAST> Parser::ParseUnary() { if (CurTok == '-') { getNextToken(); + if (CurTok == tok_number_int) { + int64_t Value; + if (!ParseIntegerValue(true, Value)) return nullptr; + return std::make_unique<IntegerExprAST>(Value); + } auto Operand = ParseUnary(); if (!Operand) return nullptr; return std::make_unique<UnaryExprAST>('-', std::move(Operand)); diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc index c47485e..fe53731 100644 --- a/lib/Parser/ParserFunction.cc +++ b/lib/Parser/ParserFunction.cc @@ -17,9 +17,7 @@ bool Parser::ParseSignedIntBound(int64_t &Out) { Lex.getLine()); return false; } - Out = Negative ? -Lex.NumVal : Lex.NumVal; - getNextToken(); - return true; + return ParseIntegerValue(Negative, Out); } // ( [BYREF|BYVAL] <name> : <type> @@ -107,7 +105,7 @@ std::optional<std::vector<ParamDecl>> Parser::ParsePrototypeArgs(bool AllowByRef } for (const ParamDecl &Prev : Params) { - if (Prev.Name == P.Name) { + if (sameIdentifier(Prev.Name, P.Name)) { fprintf(stderr, "error: Duplicate parameter name '%s' at line %d\n", P.Name.c_str(), Lex.getLine()); return std::nullopt; diff --git a/lib/Parser/ParserType.cc b/lib/Parser/ParserType.cc index 918b7f6..a57c8a6 100644 --- a/lib/Parser/ParserType.cc +++ b/lib/Parser/ParserType.cc @@ -112,19 +112,19 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody( const char *Keyword = IsClass ? "CLASS" : "TYPE"; const char *EndKeyword = IsClass ? "ENDCLASS" : "ENDTYPE"; auto AtField = [&] { - return IsClass ? (CurTok == tok_public || CurTok == tok_private) + return IsClass ? (CurTok == tok_public || CurTok == tok_private || CurTok == tok_identifier) : CurTok == tok_declare; }; std::vector<RecordFieldDecl> Fields; bool HadFieldError = false; while (CurTok != EndToken && CurTok != tok_eof) { if (AtField()) { - // Record fields are always public; class fields have no default. - bool IsPublic = !IsClass || CurTok == tok_public; + // Class fields default to public, like record fields. + bool IsPublic = CurTok != tok_private; if (ParseRecordField(Fields, IsPublic)) continue; } else { fprintf(stderr, "error: Expected %s or %s in %s %s at line %d\n", - IsClass ? "PUBLIC or PRIVATE" : "DECLARE", EndKeyword, + IsClass ? "field, PUBLIC or PRIVATE" : "DECLARE", EndKeyword, Keyword, Name.c_str(), Lex.getLine()); } HadFieldError = true; @@ -155,7 +155,7 @@ std::optional<std::vector<RecordFieldDecl>> Parser::ParseRecordBody( bool Parser::ParseRecordField(std::vector<RecordFieldDecl> &Out, bool IsPublic) { const char *Introducer = CurTok == tok_declare ? "DECLARE" : CurTok == tok_public ? "PUBLIC" : "PRIVATE"; - getNextToken(); // eat field introducer + if (CurTok != tok_identifier) getNextToken(); // optional class access keyword if (CurTok != tok_identifier) { fprintf(stderr, "error: Expected field name after %s at line %d\n", Introducer, Lex.getLine()); return false; @@ -213,7 +213,7 @@ std::string Parser::ParseTypeName(bool AllowVoid) { } if (CurTok == tok_identifier) { std::string TypeName = Lex.IdentifierStr; - if (!AllowVoid && TypeName == "VOID") { + if (!AllowVoid && sameIdentifier(TypeName, "VOID")) { fprintf(stderr, "error: VOID is not allowed here\n"); return ""; } @@ -321,9 +321,18 @@ std::unique_ptr<StmtAST> Parser::ParseConstant() { fprintf(stderr, "error: CONSTANT initializer must be a literal at line %d\n", Line); return nullptr; } - auto Value = ParsePrimary(); - if (!Value) return nullptr; - if (Negative) Value = std::make_unique<UnaryExprAST>('-', std::move(Value)); + std::unique_ptr<ExprAST> Value; + if (CurTok == tok_number_int) { + int Line = Lex.getLine(); + int64_t Integer; + if (!ParseIntegerValue(Negative, Integer)) return nullptr; + Value = std::make_unique<IntegerExprAST>(Integer); + Value->setLine(Line); + } else { + Value = ParsePrimary(); + if (!Value) return nullptr; + if (Negative) Value = std::make_unique<UnaryExprAST>('-', std::move(Value)); + } if (GetTokPrecedence() >= 0) { fprintf(stderr, "error: CONSTANT initializer must be a literal, not an expression, at line %d\n", Line); return nullptr; |
