aboutsummaryrefslogtreecommitdiff
path: root/lib/Parser
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parser')
-rw-r--r--lib/Parser/Parser.cc2
-rw-r--r--lib/Parser/ParserControlFlow.cc12
-rw-r--r--lib/Parser/ParserExpression.cc42
-rw-r--r--lib/Parser/ParserFunction.cc6
-rw-r--r--lib/Parser/ParserType.cc27
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;