#pragma once #include "cps/Identifier.h" #include "cps/Lexer.h" #include "cps/AST.h" #include "cps/TypeAST.h" #include "cps/FunctionAST.h" #include "cps/TemplateAST.h" #include #include #include #include #include #include #include namespace cps { class Parser { Lexer &Lex; int CurTok = tok_eof; bool StartsLine = true; int PrevTokLine = 0; // line of the token before CurTok bool ParsingCaseLabel = false; std::vector CaseBodyDepths; unsigned NumErrors = 0; unsigned BlockDepth = 0; // ParseBlock nesting; 1 = top level std::vector CurrentTemplate; IdentifierSet PackNames; std::map BinopPrecedence; IdentifierSet TypeNames = { "INTEGER", "REAL", "BOOLEAN", "STRING", "CHAR", "VOID", "C_INT", "C_CHAR", "C_STRING", "C_DOUBLE" }; void getNextToken(); // Line for a diagnostic about a token missing before CurTok: the previous // line when CurTok starts a new one. int missingLine() const { return StartsLine ? PrevTokLine : Lex.getLine(); } int GetTokPrecedence(); std::unique_ptr ParseExpression(); std::unique_ptr ParseAssignmentRHS(); std::unique_ptr ParseUnaryImpl(); std::unique_ptr ParseUnary(); std::unique_ptr ParsePrimaryImpl(); std::unique_ptr ParseResultMethods(std::unique_ptr Expr, int Line); std::unique_ptr ParsePrimary(); std::unique_ptr ParseBinOpRHS(int ExprPrec, std::unique_ptr LHS); std::unique_ptr ParseNumberExpr(); std::unique_ptr ParseIdentifierExpr(); std::string ParseOperatorName(int *Op = nullptr); bool ParseCalleeName(std::string &Name); std::unique_ptr ParseParenExpr(); bool ParseOptionalCallArgs(std::vector> &Args); bool diagnoseResultAccess(); static bool isBuiltinTypeToken(int Tok); std::unique_ptr ParseMemberCall( const std::string &Name, std::vector Accesses, int Line); std::string ParseTypeName(bool AllowVoid = false); std::optional> ParseTemplateArgs(); bool isTemplateCall(); bool isTemplatePack(const std::string &Name) const; std::unique_ptr ParseStatement(); std::unique_ptr ParseStatementImpl(); std::unique_ptr ParseIncludeOrGlobal(); std::unique_ptr ParseDeleteStmt(); std::unique_ptr ParseInputStmt(); std::unique_ptr ParseOutputStmt(); std::vector> ParseBlock(std::initializer_list Terminators, bool CaseBody = false); bool isCaseLabel(); bool atCaseBoundary(); std::unique_ptr ParseCaseStmt(); std::optional>> ParseExprList(char CloseDelim, bool AllowEmpty); void syncToStatementStart(); std::unique_ptr ParseIfStmt(); std::unique_ptr ParseTryStmt(); std::unique_ptr ParseWhileStmt(); std::unique_ptr ParseRepeatStmt(); std::unique_ptr ParseForStmt(); std::unique_ptr ParseDeclare(); std::unique_ptr ParseConstant(); std::unique_ptr ParseAssignStmt(); bool ParseDesignatorSuffix(std::vector &Out); static std::unique_ptr makeDesignator( const std::string &Name, std::vector Accesses, int Line); std::unique_ptr ParseTypeDecl(); std::unique_ptr ParseTemplateDecl(); std::optional> ParseRecordBody( const std::string &Name, int Line, int EndToken, std::vector> *Methods = nullptr); bool ParseRecordField(std::vector &Out, bool IsPublic); std::unique_ptr ParseFunction(const std::string &OwnerClass = {}, bool IsPublic = true, bool IsOverload = false); std::unique_ptr ParseProcedure(const std::string &OwnerClass = {}, bool IsPublic = true, bool IsOverload = false, bool IsImplicit = false); std::unique_ptr ParseFunctionBody( std::unique_ptr Proto, int EndToken, const char *EndMessage, int Line); std::unique_ptr ParseExternDecl(); std::unique_ptr ParseCallStmt(); std::unique_ptr ParseReturnStmt(); std::optional> ParsePrototypeArgs(bool AllowByRef); bool ParseIntegerValue(bool Negative, int64_t &Out); bool ParseSignedIntBound(int64_t &Out); std::unique_ptr ParseOpenFile(); std::unique_ptr ParseReadFile(); std::unique_ptr ParseWriteFile(); std::unique_ptr ParseCloseFile(); public: Parser(Lexer &L); std::vector> Parse(); bool hadError() const { return NumErrors != 0; } }; } // namespace cps