From f2b051ae3e28135cc02589f3f698c43743cca48e Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 27 Mar 2026 01:50:32 +0000 Subject: feat: generalize typed array support --- lib/Parser/Parser.cc | 72 +++++++++++++++++++++++++++++++++++--------- lib/Parser/ParserFunction.cc | 49 ++++++++++++++++++++++-------- 2 files changed, 95 insertions(+), 26 deletions(-) (limited to 'lib/Parser') diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc index 9bdd821..322cdb9 100644 --- a/lib/Parser/Parser.cc +++ b/lib/Parser/Parser.cc @@ -1,5 +1,6 @@ #include "cps/Parser.h" #include "cps/FunctionAST.h" +#include using namespace cps; @@ -96,6 +97,41 @@ std::unique_ptr Parser::ParseIdentifierExpr() { return std::make_unique(IdName); } +std::string Parser::ParseTypeName(bool AllowVoid) { + if (CurTok == tok_integer_kw) { + getNextToken(); + return "INTEGER"; + } + if (CurTok == tok_real_kw) { + getNextToken(); + return "REAL"; + } + if (CurTok == tok_boolean_kw) { + getNextToken(); + return "BOOLEAN"; + } + if (CurTok == tok_string_kw) { + getNextToken(); + return "STRING"; + } + if (CurTok == tok_char_kw) { + getNextToken(); + return "CHAR"; + } + if (CurTok == tok_identifier) { + std::string TypeName = Lex.IdentifierStr; + if (!AllowVoid && TypeName == "VOID") { + fprintf(stderr, "Error: VOID is not allowed here\n"); + return ""; + } + getNextToken(); + return TypeName; + } + + fprintf(stderr, "Error: Unknown type name\n"); + return ""; +} + std::unique_ptr Parser::ParseStringBuiltin(const std::string &FuncName) { getNextToken(); if (CurTok != '(') { @@ -146,6 +182,11 @@ std::unique_ptr Parser::ParsePrimary() { getNextToken(); return Res; } + case tok_char_literal: { + auto Res = std::make_unique(Lex.CharVal); + getNextToken(); + return Res; + } case tok_length: return ParseStringBuiltin("LENGTH"); case tok_mid: return ParseStringBuiltin("MID"); case tok_right: return ParseStringBuiltin("RIGHT"); @@ -176,6 +217,16 @@ std::unique_ptr Parser::ParseUnary() { if (!Operand) return nullptr; return std::make_unique(tok_not, std::move(Operand)); } + + if (CurTok == '-') { + int Line = Lex.getLine(); + getNextToken(); + auto Operand = ParseUnary(); + if (!Operand) return nullptr; + auto Zero = std::make_unique(0); + return std::make_unique('-', std::move(Zero), std::move(Operand), Line); + } + return ParsePrimary(); } @@ -268,26 +319,19 @@ std::unique_ptr Parser::ParseDeclare() { return nullptr; } getNextToken(); - - if (CurTok != tok_integer_kw) { - fprintf(stderr, "Error: Only INTEGER arrays supported currently\n"); - return nullptr; + + std::string TypeStr = ParseTypeName(false); + if (TypeStr.empty()) { + return nullptr; } - getNextToken(); - return std::make_unique(Name, std::move(Bounds), "INTEGER"); + return std::make_unique(Name, std::move(Bounds), TypeStr); } else { - std::string TypeStr; - if (CurTok == tok_integer_kw) TypeStr = "INTEGER"; - else if (CurTok == tok_real_kw) TypeStr = "REAL"; - else if (CurTok == tok_boolean_kw) TypeStr = "BOOLEAN"; - else if (CurTok == tok_string_kw) TypeStr = "STRING"; - else { - fprintf(stderr, "Error: Unknown type in declaration\n"); + std::string TypeStr = ParseTypeName(false); + if (TypeStr.empty()) { return nullptr; } - getNextToken(); return std::make_unique(Name, TypeStr); } } diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc index d689aa6..05b1e12 100644 --- a/lib/Parser/ParserFunction.cc +++ b/lib/Parser/ParserFunction.cc @@ -1,5 +1,6 @@ #include "cps/Parser.h" #include "cps/FunctionAST.h" +#include #include using namespace cps; @@ -34,15 +35,10 @@ std::vector> Parser::ParsePrototypeAr } getNextToken(); - std::string Type = "INTEGER"; - if (CurTok == tok_integer_kw) { - getNextToken(); - } else if (CurTok == tok_identifier) { - Type = Lex.IdentifierStr; - getNextToken(); - } else { - fprintf(stderr, "Error: Expected type (e.g. INTEGER) for argument '%s'\n", Name.c_str()); - return Args; + std::string Type = ParseTypeName(false); + if (Type.empty()) { + fprintf(stderr, "Error: Expected argument type for '%s'\n", Name.c_str()); + return Args; } Args.emplace_back(Name, Type, IsRef); @@ -58,18 +54,26 @@ std::vector> Parser::ParsePrototypeAr return Args; } - std::unique_ptr Parser::ParseFunction() { getNextToken(); + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: Expected function name\n"); + return nullptr; + } + std::string Name = Lex.IdentifierStr; getNextToken(); auto Args = ParsePrototypeArgs(); std::string RetType = "INTEGER"; - if (CurTok == tok_returns) { - getNextToken(); + if (CurTok == tok_returns) { getNextToken(); + RetType = ParseTypeName(true); + if (RetType.empty()) { + fprintf(stderr, "Error: Expected return type for function '%s'\n", Name.c_str()); + return nullptr; + } } auto Proto = std::make_unique(Name, std::move(Args), RetType); @@ -80,6 +84,11 @@ std::unique_ptr Parser::ParseFunction() { if (Stmt) Body.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_endfunction) getNextToken(); } + + if (CurTok != tok_endfunction) { + fprintf(stderr, "Error: expected ENDFUNCTION\n"); + return nullptr; + } getNextToken(); return std::make_unique(std::move(Proto), std::move(Body)); @@ -87,6 +96,11 @@ std::unique_ptr Parser::ParseFunction() { std::unique_ptr Parser::ParseProcedure() { getNextToken(); + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: Expected procedure name\n"); + return nullptr; + } + std::string Name = Lex.IdentifierStr; getNextToken(); @@ -99,6 +113,11 @@ std::unique_ptr Parser::ParseProcedure() { if (Stmt) Body.push_back(std::move(Stmt)); else if (CurTok != tok_eof && CurTok != tok_endprocedure) getNextToken(); } + + if (CurTok != tok_endprocedure) { + fprintf(stderr, "Error: expected ENDPROCEDURE\n"); + return nullptr; + } getNextToken(); return std::make_unique(std::move(Proto), std::move(Body)); @@ -106,6 +125,11 @@ std::unique_ptr Parser::ParseProcedure() { std::unique_ptr Parser::ParseCallStmt() { getNextToken(); + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: Expected callee name after CALL\n"); + return nullptr; + } + std::string Callee = Lex.IdentifierStr; getNextToken(); @@ -115,6 +139,7 @@ std::unique_ptr Parser::ParseCallStmt() { while (CurTok != ')') { auto Arg = ParseExpression(); if (Arg) Args.push_back(std::move(Arg)); + else return nullptr; if (CurTok == ')') break; if (CurTok != ',') { -- cgit v1.3.1-4-g156e