diff --git a/grammar/MXParser.g4 b/grammar/MXParser.g4 index ce26d09..768249e 100644 --- a/grammar/MXParser.g4 +++ b/grammar/MXParser.g4 @@ -52,12 +52,12 @@ expr ; basic_expr - : THIS - | LPAREN expr RPAREN - | ID - | ID LPAREN (expr (COMMA expr)*)? RPAREN - | formatted_string - | constant + : THIS #this_expr + | LPAREN expr RPAREN #paren_expr + | ID #id_expr + | ID LPAREN (expr (COMMA expr)*)? RPAREN #function_call_expr + | formatted_string #formatted_string_expr + | constant #constant_expr ; formatted_string : FORMAT_STRING_WHOLE | (FORMAT_STRING_HEAD expr (FORMAT_STRING_BODY expr)*? FORMAT_STRING_TAIL); diff --git a/include/ast/ast.h b/include/ast/ast.h new file mode 100644 index 0000000..5997c1a --- /dev/null +++ b/include/ast/ast.h @@ -0,0 +1,8 @@ +#ifndef AST_H +#define AST_H +#include "astnode.h" +#include "astnode_visitor.h" +#include "expr_astnode.h" +#include "statement_astnode.h" +#include "structural_astnode.h" +#endif // AST_H \ No newline at end of file diff --git a/include/ast/astnode.h b/include/ast/astnode.h new file mode 100644 index 0000000..57ac448 --- /dev/null +++ b/include/ast/astnode.h @@ -0,0 +1,31 @@ +#ifndef ASTNODE_H +#define ASTNODE_H +#include +#include +#include +using IdentifierType = std::string; +struct ArrayType { + bool has_base_type; + IdentifierType basetype; + size_t level; +}; +using ExprTypeInfo = std::variant; +class ASTNodeVisitorBase { + public: + virtual ~ASTNodeVisitorBase() = default; + virtual void visit(class ASTNodeBase *context) = 0; +}; +enum class ASTNodeType { + +}; + +class ASTNodeBase { + ASTNodeType type; + // std::vector> children; + size_t start_line, start_char_pos, end_line, end_char_pos; + + public: + virtual ~ASTNodeBase() = default; + virtual void accept(class ASTNodeVisitorBase *visitor) = 0; +}; +#endif \ No newline at end of file diff --git a/include/ast/astnode_visitor.h b/include/ast/astnode_visitor.h new file mode 100644 index 0000000..14145fa --- /dev/null +++ b/include/ast/astnode_visitor.h @@ -0,0 +1,6 @@ +#ifndef ASTNODE_VISITOR_H +#define ASTNODE_VISITOR_H +#include "astnode.h" +#include "expr_astnode.h" +class ASTNodeVisitor : public ASTNodeVisitorBase {}; +#endif \ No newline at end of file diff --git a/include/ast/expr_astnode.h b/include/ast/expr_astnode.h new file mode 100644 index 0000000..0b5da73 --- /dev/null +++ b/include/ast/expr_astnode.h @@ -0,0 +1,126 @@ +#ifndef EXPR_ASTNODE_H +#define EXPR_ASTNODE_H +#include +#include +#include +#include "astnode.h" + +class Expr_ASTNode : public ASTNodeBase { + ExprTypeInfo expr_type_info; + + public: + virtual ~Expr_ASTNode() = default; +}; + +class BasicExpr_ASTNode : public Expr_ASTNode {}; // This is a virtual class +class NewArrayExpr_ASTNode : public Expr_ASTNode { + bool has_initial_value; + std::shared_ptr initial_value; +}; +class NewConstructExpr_ASTNode : public Expr_ASTNode {}; +class NewExpr_ASTNode : public Expr_ASTNode {}; +class AccessExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr base; + IdentifierType member; +}; +class MemberVariableAccessExpr_ASTNode : public AccessExpr_ASTNode {}; +class MemberFunctionAccessExpr_ASTNode : public AccessExpr_ASTNode { + std::vector> arguments; +}; +class IndexExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr base; + std::vector> indices; +}; +class SuffixExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr base; +}; +class PrefixExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr base; +}; +class OppositeExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr base; +}; +class LNotExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class BNotExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class MDMExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class PMExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class RLExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class GGLLExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class NEExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class BAndExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class BXorExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class BOrExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class LAndExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class LOrExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr left; + std::shared_ptr right; +}; +class TernaryExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr condition; + std::shared_ptr src1; + std::shared_ptr src2; +}; +class AssignExpr_ASTNode : public Expr_ASTNode { + std::shared_ptr dest; + std::shared_ptr src; +}; + +class ThisExpr_ASTNode : public BasicExpr_ASTNode {}; +class ParenExpr_ASTNode : public BasicExpr_ASTNode { + std::shared_ptr expr; +}; +class IDExpr_ASTNode : public BasicExpr_ASTNode { + IdentifierType id; +}; +class FunctionCallExpr_ASTNode : public BasicExpr_ASTNode { + IdentifierType func_name; + std::vector> arguments; +}; +class FormattedStringExpr_ASTNode : public BasicExpr_ASTNode { + using SegmentType = std::variant>; + std::vector segments; +}; +struct NullType {}; +using AtomicConstantType = std::variant; +struct ArrayConstantType { + std::vector, NullType, AtomicConstantType>> elements; + size_t level; +}; +class ConstantExpr_ASTNode : public BasicExpr_ASTNode { + std::variant value; +}; + +#endif // EXPR_ASTNODE_H \ No newline at end of file diff --git a/include/ast/statement_astnode.h b/include/ast/statement_astnode.h new file mode 100644 index 0000000..858dc7b --- /dev/null +++ b/include/ast/statement_astnode.h @@ -0,0 +1,42 @@ +#ifndef STATEMENT_ASTNODE_H +#define STATEMENT_ASTNODE_H +#include +#include "astnode.h" +#include "expr_astnode.h" +class Statement_ASTNode : public ASTNodeBase { + public: + virtual ~Statement_ASTNode() = default; +}; + +class EmptyStatement_ASTNode : public Statement_ASTNode {}; +class DefinitionStatement_ASTNode : public Statement_ASTNode { + ExprTypeInfo type; + std::vector>> vars; +}; +class ExprStatement_ASTNode : public Statement_ASTNode { + std::shared_ptr expr; +}; +class IfStatement_ASTNode : public Statement_ASTNode { + bool has_else_clause; + std::shared_ptr condition; + std::shared_ptr if_clause; + std::shared_ptr else_clause; +}; +class WhileStatement_ASTNode : public Statement_ASTNode { + std::shared_ptr condition; + std::shared_ptr loop_body; +}; +class ForStatement_ASTNode : public Statement_ASTNode { + std::shared_ptr initial; + std::shared_ptr condition; + std::shared_ptr update; + std::shared_ptr loop_body; +}; +class JmpStatement_ASTNode : public Statement_ASTNode { + std::shared_ptr return_value; +}; +class SuiteStatement_ASTNode : public Statement_ASTNode { + std::vector> statements; +}; + +#endif // STATEMENT_ASTNODE_H \ No newline at end of file diff --git a/include/ast/structural_astnode.h b/include/ast/structural_astnode.h new file mode 100644 index 0000000..99d7fb0 --- /dev/null +++ b/include/ast/structural_astnode.h @@ -0,0 +1,27 @@ +#ifndef STRUCTURAL_ASTNODE_H +#define STRUCTURAL_ASTNODE_H +#include +#include +#include +#include "astnode.h" +#include "expr_astnode.h" +#include "statement_astnode.h" +class FuncDef_ASTNode : public ASTNodeBase { + IdentifierType func_name; + std::vector> params; + std::shared_ptr func_body; +}; +class Constructor_ASTNode : public FuncDef_ASTNode {}; +class ClassVariable_ASTNode : public DefinitionStatement_ASTNode {}; +class ClassDef_ASTNode : public ASTNodeBase { + private: + using ClassElement = std::variant, std::shared_ptr, + std::shared_ptr>; + std::vector elements; +}; +class Program_ASTNode : public ASTNodeBase { + using ProgramElement = std::variant, std::shared_ptr, + std::shared_ptr>; + std::vector elements; +}; +#endif \ No newline at end of file diff --git a/include/semantic/semantic.h b/include/semantic/semantic.h index a549e60..6c45d2d 100644 --- a/include/semantic/semantic.h +++ b/include/semantic/semantic.h @@ -1,5 +1,18 @@ #ifndef SEMANTIC_H #define SEMANTIC_H #include -int SemanticCheck(std::istream &fin); +#include "ast/ast.h" +#include "visitor.h" + +class SemanticError : public std::exception { + std::string msg; + int error_code; + + public: + SemanticError(const std::string &msg, int error_code) : msg(msg), error_code(error_code) {} + const char *what() const noexcept override { return msg.c_str(); } + int GetErrorCode() const { return error_code; } +}; +std::shared_ptr BuildAST(Visitor *visitor, antlr4::tree::ParseTree *tree); +void SemanticCheck(std::istream &fin, std::shared_ptr &ast); #endif \ No newline at end of file diff --git a/include/semantic/visitor.h b/include/semantic/visitor.h index b2a3129..e22511e 100644 --- a/include/semantic/visitor.h +++ b/include/semantic/visitor.h @@ -1,15 +1,57 @@ #ifndef VISITOR_H #define VISITOR_H + #include "MXParserVisitor.h" + class Visitor : public MXParserVisitor { public: - virtual std::any visitMxprog(MXParser::MxprogContext *context); - virtual std::any visitFunction(MXParser::FunctionContext *context); - virtual std::any visitType(MXParser::TypeContext *context); - virtual std::any visitBlock(MXParser::BlockContext *context); - virtual std::any visitStatement(MXParser::StatementContext *context); - virtual std::any visitExpression(MXParser::ExpressionContext *context); - virtual std::any visitReturnStmt(MXParser::ReturnStmtContext *context); - virtual std::any visitIfStmt(MXParser::IfStmtContext *context); + std::any visitMxprog(MXParser::MxprogContext *context) override; + std::any visitFunction_def(MXParser::Function_defContext *context) override; + std::any visitClass_def(MXParser::Class_defContext *context) override; + std::any visitClass_var_def(MXParser::Class_var_defContext *context) override; + std::any visitClass_constructor(MXParser::Class_constructorContext *context) override; + std::any visitSuite(MXParser::SuiteContext *context) override; + std::any visitEmpty_statement(MXParser::Empty_statementContext *context) override; + std::any visitDefinition_statement(MXParser::Definition_statementContext *context) override; + std::any visitExpr_statement(MXParser::Expr_statementContext *context) override; + std::any visitIf_statement(MXParser::If_statementContext *context) override; + std::any visitWhile_statement(MXParser::While_statementContext *context) override; + std::any visitFor_statement(MXParser::For_statementContext *context) override; + std::any visitJmp_statement(MXParser::Jmp_statementContext *context) override; + std::any visitSuite_statement(MXParser::Suite_statementContext *context) override; + std::any visitDefine_statement(MXParser::Define_statementContext *context) override; + std::any visitGgll_expression(MXParser::Ggll_expressionContext *context) override; + std::any visitBxor_expression(MXParser::Bxor_expressionContext *context) override; + std::any visitSuffix_expression(MXParser::Suffix_expressionContext *context) override; + std::any visitLand_expression(MXParser::Land_expressionContext *context) override; + std::any visitPm_expression(MXParser::Pm_expressionContext *context) override; + std::any visitIndex_expression(MXParser::Index_expressionContext *context) override; + std::any visitOpposite_expression(MXParser::Opposite_expressionContext *context) override; + std::any visitNew_array_expression(MXParser::New_array_expressionContext *context) override; + std::any visitBasic_expression(MXParser::Basic_expressionContext *context) override; + std::any visitAccess_expression(MXParser::Access_expressionContext *context) override; + std::any visitBand_expression(MXParser::Band_expressionContext *context) override; + std::any visitNew_construct_expression(MXParser::New_construct_expressionContext *context) override; + std::any visitTernary_expression(MXParser::Ternary_expressionContext *context) override; + std::any visitBnot_expression(MXParser::Bnot_expressionContext *context) override; + std::any visitLnot_expression(MXParser::Lnot_expressionContext *context) override; + std::any visitPrefix_expression(MXParser::Prefix_expressionContext *context) override; + std::any visitRl_expression(MXParser::Rl_expressionContext *context) override; + std::any visitAssign_expression(MXParser::Assign_expressionContext *context) override; + std::any visitMdm_expression(MXParser::Mdm_expressionContext *context) override; + std::any visitNew_expression(MXParser::New_expressionContext *context) override; + std::any visitNe_expression(MXParser::Ne_expressionContext *context) override; + std::any visitBor_expression(MXParser::Bor_expressionContext *context) override; + std::any visitLor_expression(MXParser::Lor_expressionContext *context) override; + std::any visitThis_expr(MXParser::This_exprContext *context) override; + std::any visitParen_expr(MXParser::Paren_exprContext *context) override; + std::any visitId_expr(MXParser::Id_exprContext *context) override; + std::any visitFunction_call_expr(MXParser::Function_call_exprContext *context) override; + std::any visitFormatted_string_expr(MXParser::Formatted_string_exprContext *context) override; + std::any visitConstant_expr(MXParser::Constant_exprContext *context) override; + std::any visitFormatted_string(MXParser::Formatted_stringContext *context) override; + std::any visitConstant(MXParser::ConstantContext *context) override; + std::any visitType(MXParser::TypeContext *context) override; }; -#endif \ No newline at end of file + +#endif // VISITOR_H \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2879d9..11a7386 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(ast) add_subdirectory(semantic) add_executable(code main.cpp) target_link_libraries(code semantic argparse) diff --git a/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt new file mode 100644 index 0000000..2513fe2 --- /dev/null +++ b/src/ast/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(${CMAKE_SOURCE_DIR}/include/ast) +file(GLOB AST_SOURCES "*.cpp") +add_library(ast STATIC ${AST_SOURCES}) \ No newline at end of file diff --git a/src/ast/astnode.cpp b/src/ast/astnode.cpp new file mode 100644 index 0000000..df9f623 --- /dev/null +++ b/src/ast/astnode.cpp @@ -0,0 +1,2 @@ +#include "astnode.h" +#include "astnode_visitor.h" \ No newline at end of file diff --git a/src/ast/astnode_visitor.cpp b/src/ast/astnode_visitor.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/ast/expr_astnode.cpp b/src/ast/expr_astnode.cpp new file mode 100644 index 0000000..71824f6 --- /dev/null +++ b/src/ast/expr_astnode.cpp @@ -0,0 +1 @@ +#include "expr_astnode.h" \ No newline at end of file diff --git a/src/ast/statement_astnode.cpp b/src/ast/statement_astnode.cpp new file mode 100644 index 0000000..7d84b2b --- /dev/null +++ b/src/ast/statement_astnode.cpp @@ -0,0 +1 @@ +#include "statement_astnode.h" \ No newline at end of file diff --git a/src/ast/structural_astnode.cpp b/src/ast/structural_astnode.cpp new file mode 100644 index 0000000..9864b72 --- /dev/null +++ b/src/ast/structural_astnode.cpp @@ -0,0 +1 @@ +#include "structural_astnode.h" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bb38701..75343db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,8 +21,18 @@ int main(int argc, char **argv) { auto input_file = program.get("input"); auto output_file = program.get("output"); std::ifstream fin(input_file); - int err_code = SemanticCheck(fin); - if (err_code != 0) return err_code; - + std::shared_ptr ast; + try { + SemanticCheck(fin, ast); + } catch (const SemanticError &err) { + std::cout << err.what() << std::endl; + return err.GetErrorCode(); + } catch (const std::exception &err) { + std::cout << "Unknown error: " << err.what() << std::endl; + return 254; + } catch (...) { + std::cout << "Unknown error without message" << std::endl; + return 255; + } return 0; } \ No newline at end of file diff --git a/src/semantic/CMakeLists.txt b/src/semantic/CMakeLists.txt index 94b9fd1..a2630c7 100644 --- a/src/semantic/CMakeLists.txt +++ b/src/semantic/CMakeLists.txt @@ -1,9 +1,10 @@ include_directories(/usr/include/antlr4-runtime/) include_directories(${CMAKE_SOURCE_DIR}/include/semantic) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/antlr-generated) file(GLOB ANLTR_SOURCES "antlr-generated/*.cpp") file(GLOB SEMANTIC_SOURCES "*.cpp") add_library(mx-antlr STATIC ${ANLTR_SOURCES}) add_library(semantic STATIC ${SEMANTIC_SOURCES}) +target_include_directories(semantic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/antlr-generated) +target_include_directories(semantic PUBLIC /usr/include/antlr4-runtime/) target_link_libraries(mx-antlr PUBLIC antlr4-runtime) -target_link_libraries(semantic PUBLIC antlr4-runtime mx-antlr) \ No newline at end of file +target_link_libraries(semantic PUBLIC antlr4-runtime mx-antlr ast) \ No newline at end of file diff --git a/src/semantic/antlr-generated/MXParser.cpp b/src/semantic/antlr-generated/MXParser.cpp index eacfbf0..7e5c8a6 100644 --- a/src/semantic/antlr-generated/MXParser.cpp +++ b/src/semantic/antlr-generated/MXParser.cpp @@ -2660,59 +2660,137 @@ MXParser::Basic_exprContext::Basic_exprContext(ParserRuleContext *parent, size_t : ParserRuleContext(parent, invokingState) { } -tree::TerminalNode* MXParser::Basic_exprContext::THIS() { - return getToken(MXParser::THIS, 0); -} - -tree::TerminalNode* MXParser::Basic_exprContext::LPAREN() { - return getToken(MXParser::LPAREN, 0); -} - -std::vector MXParser::Basic_exprContext::expr() { - return getRuleContexts(); -} - -MXParser::ExprContext* MXParser::Basic_exprContext::expr(size_t i) { - return getRuleContext(i); -} - -tree::TerminalNode* MXParser::Basic_exprContext::RPAREN() { - return getToken(MXParser::RPAREN, 0); -} - -tree::TerminalNode* MXParser::Basic_exprContext::ID() { - return getToken(MXParser::ID, 0); -} - -std::vector MXParser::Basic_exprContext::COMMA() { - return getTokens(MXParser::COMMA); -} - -tree::TerminalNode* MXParser::Basic_exprContext::COMMA(size_t i) { - return getToken(MXParser::COMMA, i); -} - -MXParser::Formatted_stringContext* MXParser::Basic_exprContext::formatted_string() { - return getRuleContext(0); -} - -MXParser::ConstantContext* MXParser::Basic_exprContext::constant() { - return getRuleContext(0); -} - size_t MXParser::Basic_exprContext::getRuleIndex() const { return MXParser::RuleBasic_expr; } +void MXParser::Basic_exprContext::copyFrom(Basic_exprContext *ctx) { + ParserRuleContext::copyFrom(ctx); +} -std::any MXParser::Basic_exprContext::accept(tree::ParseTreeVisitor *visitor) { +//----------------- Paren_exprContext ------------------------------------------------------------------ + +tree::TerminalNode* MXParser::Paren_exprContext::LPAREN() { + return getToken(MXParser::LPAREN, 0); +} + +MXParser::ExprContext* MXParser::Paren_exprContext::expr() { + return getRuleContext(0); +} + +tree::TerminalNode* MXParser::Paren_exprContext::RPAREN() { + return getToken(MXParser::RPAREN, 0); +} + +MXParser::Paren_exprContext::Paren_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::Paren_exprContext::accept(tree::ParseTreeVisitor *visitor) { if (auto parserVisitor = dynamic_cast(visitor)) - return parserVisitor->visitBasic_expr(this); + return parserVisitor->visitParen_expr(this); else return visitor->visitChildren(this); } +//----------------- Constant_exprContext ------------------------------------------------------------------ +MXParser::ConstantContext* MXParser::Constant_exprContext::constant() { + return getRuleContext(0); +} + +MXParser::Constant_exprContext::Constant_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::Constant_exprContext::accept(tree::ParseTreeVisitor *visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitConstant_expr(this); + else + return visitor->visitChildren(this); +} +//----------------- This_exprContext ------------------------------------------------------------------ + +tree::TerminalNode* MXParser::This_exprContext::THIS() { + return getToken(MXParser::THIS, 0); +} + +MXParser::This_exprContext::This_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::This_exprContext::accept(tree::ParseTreeVisitor *visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitThis_expr(this); + else + return visitor->visitChildren(this); +} +//----------------- Id_exprContext ------------------------------------------------------------------ + +tree::TerminalNode* MXParser::Id_exprContext::ID() { + return getToken(MXParser::ID, 0); +} + +MXParser::Id_exprContext::Id_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::Id_exprContext::accept(tree::ParseTreeVisitor *visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitId_expr(this); + else + return visitor->visitChildren(this); +} +//----------------- Formatted_string_exprContext ------------------------------------------------------------------ + +MXParser::Formatted_stringContext* MXParser::Formatted_string_exprContext::formatted_string() { + return getRuleContext(0); +} + +MXParser::Formatted_string_exprContext::Formatted_string_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::Formatted_string_exprContext::accept(tree::ParseTreeVisitor *visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitFormatted_string_expr(this); + else + return visitor->visitChildren(this); +} +//----------------- Function_call_exprContext ------------------------------------------------------------------ + +tree::TerminalNode* MXParser::Function_call_exprContext::ID() { + return getToken(MXParser::ID, 0); +} + +tree::TerminalNode* MXParser::Function_call_exprContext::LPAREN() { + return getToken(MXParser::LPAREN, 0); +} + +tree::TerminalNode* MXParser::Function_call_exprContext::RPAREN() { + return getToken(MXParser::RPAREN, 0); +} + +std::vector MXParser::Function_call_exprContext::expr() { + return getRuleContexts(); +} + +MXParser::ExprContext* MXParser::Function_call_exprContext::expr(size_t i) { + return getRuleContext(i); +} + +std::vector MXParser::Function_call_exprContext::COMMA() { + return getTokens(MXParser::COMMA); +} + +tree::TerminalNode* MXParser::Function_call_exprContext::COMMA(size_t i) { + return getToken(MXParser::COMMA, i); +} + +MXParser::Function_call_exprContext::Function_call_exprContext(Basic_exprContext *ctx) { copyFrom(ctx); } + + +std::any MXParser::Function_call_exprContext::accept(tree::ParseTreeVisitor *visitor) { + if (auto parserVisitor = dynamic_cast(visitor)) + return parserVisitor->visitFunction_call_expr(this); + else + return visitor->visitChildren(this); +} MXParser::Basic_exprContext* MXParser::basic_expr() { Basic_exprContext *_localctx = _tracker.createInstance(_ctx, getState()); enterRule(_localctx, 18, MXParser::RuleBasic_expr); @@ -2730,6 +2808,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { _errHandler->sync(this); switch (getInterpreter()->adaptivePredict(_input, 35, _ctx)) { case 1: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 1); setState(306); match(MXParser::THIS); @@ -2737,6 +2816,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { } case 2: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 2); setState(307); match(MXParser::LPAREN); @@ -2748,6 +2828,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { } case 3: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 3); setState(311); match(MXParser::ID); @@ -2755,6 +2836,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { } case 4: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 4); setState(312); match(MXParser::ID); @@ -2787,6 +2869,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { } case 5: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 5); setState(325); formatted_string(); @@ -2794,6 +2877,7 @@ MXParser::Basic_exprContext* MXParser::basic_expr() { } case 6: { + _localctx = _tracker.createInstance(_localctx); enterOuterAlt(_localctx, 6); setState(326); constant(); diff --git a/src/semantic/antlr-generated/MXParser.h b/src/semantic/antlr-generated/MXParser.h index 1c96faa..9ca14f7 100644 --- a/src/semantic/antlr-generated/MXParser.h +++ b/src/semantic/antlr-generated/MXParser.h @@ -610,21 +610,76 @@ public: class Basic_exprContext : public antlr4::ParserRuleContext { public: Basic_exprContext(antlr4::ParserRuleContext *parent, size_t invokingState); - virtual size_t getRuleIndex() const override; - antlr4::tree::TerminalNode *THIS(); - antlr4::tree::TerminalNode *LPAREN(); - std::vector expr(); - ExprContext* expr(size_t i); - antlr4::tree::TerminalNode *RPAREN(); - antlr4::tree::TerminalNode *ID(); - std::vector COMMA(); - antlr4::tree::TerminalNode* COMMA(size_t i); - Formatted_stringContext *formatted_string(); - ConstantContext *constant(); + + Basic_exprContext() = default; + void copyFrom(Basic_exprContext *context); + using antlr4::ParserRuleContext::copyFrom; + virtual size_t getRuleIndex() const override; + + + }; + + class Paren_exprContext : public Basic_exprContext { + public: + Paren_exprContext(Basic_exprContext *ctx); + + antlr4::tree::TerminalNode *LPAREN(); + ExprContext *expr(); + antlr4::tree::TerminalNode *RPAREN(); + + virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; + }; + + class Constant_exprContext : public Basic_exprContext { + public: + Constant_exprContext(Basic_exprContext *ctx); + + ConstantContext *constant(); + + virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; + }; + + class This_exprContext : public Basic_exprContext { + public: + This_exprContext(Basic_exprContext *ctx); + + antlr4::tree::TerminalNode *THIS(); + + virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; + }; + + class Id_exprContext : public Basic_exprContext { + public: + Id_exprContext(Basic_exprContext *ctx); + + antlr4::tree::TerminalNode *ID(); + + virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; + }; + + class Formatted_string_exprContext : public Basic_exprContext { + public: + Formatted_string_exprContext(Basic_exprContext *ctx); + + Formatted_stringContext *formatted_string(); + + virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; + }; + + class Function_call_exprContext : public Basic_exprContext { + public: + Function_call_exprContext(Basic_exprContext *ctx); + + antlr4::tree::TerminalNode *ID(); + antlr4::tree::TerminalNode *LPAREN(); + antlr4::tree::TerminalNode *RPAREN(); + std::vector expr(); + ExprContext* expr(size_t i); + std::vector COMMA(); + antlr4::tree::TerminalNode* COMMA(size_t i); virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override; - }; Basic_exprContext* basic_expr(); diff --git a/src/semantic/antlr-generated/MXParserVisitor.h b/src/semantic/antlr-generated/MXParserVisitor.h index 1381949..f2908df 100644 --- a/src/semantic/antlr-generated/MXParserVisitor.h +++ b/src/semantic/antlr-generated/MXParserVisitor.h @@ -95,7 +95,17 @@ public: virtual std::any visitLor_expression(MXParser::Lor_expressionContext *context) = 0; - virtual std::any visitBasic_expr(MXParser::Basic_exprContext *context) = 0; + virtual std::any visitThis_expr(MXParser::This_exprContext *context) = 0; + + virtual std::any visitParen_expr(MXParser::Paren_exprContext *context) = 0; + + virtual std::any visitId_expr(MXParser::Id_exprContext *context) = 0; + + virtual std::any visitFunction_call_expr(MXParser::Function_call_exprContext *context) = 0; + + virtual std::any visitFormatted_string_expr(MXParser::Formatted_string_exprContext *context) = 0; + + virtual std::any visitConstant_expr(MXParser::Constant_exprContext *context) = 0; virtual std::any visitFormatted_string(MXParser::Formatted_stringContext *context) = 0; diff --git a/src/semantic/semantic.cpp b/src/semantic/semantic.cpp index 530fa12..9cf2ad0 100644 --- a/src/semantic/semantic.cpp +++ b/src/semantic/semantic.cpp @@ -3,15 +3,37 @@ #include "MXLexer.h" #include "MXParser.h" #include "antlr4-runtime.h" +#include "ast/ast.h" #include "visitor.h" -int SemanticCheck(std::istream &fin) { + +class MXErrorListener : public antlr4::BaseErrorListener { + bool no_problem; + + public: + MXErrorListener() : no_problem(true) {} + void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token *offendingSymbol, size_t line, + size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override { + std::cout << "line " << line << ":" << charPositionInLine << " AT " + << offendingSymbol->getText() << ": " << msg << std::endl; + no_problem = false; + } + bool IsOk() { return no_problem; } +}; +std::shared_ptr BuildAST(Visitor *visitor, antlr4::tree::ParseTree *tree) { ; } +std::shared_ptr CheckAndDecorate(std::shared_ptr src) { ; } + +void SemanticCheck(std::istream &fin, std::shared_ptr &ast_out) { antlr4::ANTLRInputStream input(fin); MXLexer lexer(&input); antlr4::CommonTokenStream tokens(&lexer); tokens.fill(); MXParser parser(&tokens); + parser.removeErrorListeners(); + MXErrorListener error_listener; + parser.addErrorListener(&error_listener); antlr4::tree::ParseTree *tree = parser.mxprog(); + if (!error_listener.IsOk()) throw SemanticError("Fatal error: syntax error", 1); Visitor visitor; - visitor.visit(tree); - return 0; + std::shared_ptr ast = BuildAST(&visitor, tree); + ast_out = CheckAndDecorate(ast); } \ No newline at end of file diff --git a/src/semantic/visitor.cpp b/src/semantic/visitor.cpp index 42fb7c9..4369d97 100644 --- a/src/semantic/visitor.cpp +++ b/src/semantic/visitor.cpp @@ -1,41 +1,128 @@ #include "visitor.h" +#include -std::any Visitor::visitMxprog(MXParser::MxprogContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitMxprog(MXParser::MxprogContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitFunction_def(MXParser::Function_defContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitFunction(MXParser::FunctionContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitClass_def(MXParser::Class_defContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitClass_var_def(MXParser::Class_var_defContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitType(MXParser::TypeContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitClass_constructor(MXParser::Class_constructorContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitBlock(MXParser::BlockContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitSuite(MXParser::SuiteContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitEmpty_statement(MXParser::Empty_statementContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitStatement(MXParser::StatementContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitDefinition_statement(MXParser::Definition_statementContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitExpression(MXParser::ExpressionContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitExpr_statement(MXParser::Expr_statementContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitReturnStmt(MXParser::ReturnStmtContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitIf_statement(MXParser::If_statementContext *context) { + throw std::runtime_error("Not implemented"); } - -std::any Visitor::visitIfStmt(MXParser::IfStmtContext *context) { - // 空的函数体 - return {}; +std::any Visitor::visitWhile_statement(MXParser::While_statementContext *context) { + throw std::runtime_error("Not implemented"); } +std::any Visitor::visitFor_statement(MXParser::For_statementContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitJmp_statement(MXParser::Jmp_statementContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitSuite_statement(MXParser::Suite_statementContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitDefine_statement(MXParser::Define_statementContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitGgll_expression(MXParser::Ggll_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitBxor_expression(MXParser::Bxor_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitSuffix_expression(MXParser::Suffix_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitLand_expression(MXParser::Land_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitPm_expression(MXParser::Pm_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitIndex_expression(MXParser::Index_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitOpposite_expression(MXParser::Opposite_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitNew_array_expression(MXParser::New_array_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitBasic_expression(MXParser::Basic_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitAccess_expression(MXParser::Access_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitBand_expression(MXParser::Band_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitNew_construct_expression(MXParser::New_construct_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitTernary_expression(MXParser::Ternary_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitBnot_expression(MXParser::Bnot_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitLnot_expression(MXParser::Lnot_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitPrefix_expression(MXParser::Prefix_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitRl_expression(MXParser::Rl_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitAssign_expression(MXParser::Assign_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitMdm_expression(MXParser::Mdm_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitNew_expression(MXParser::New_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitNe_expression(MXParser::Ne_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitBor_expression(MXParser::Bor_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitLor_expression(MXParser::Lor_expressionContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitThis_expr(MXParser::This_exprContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitParen_expr(MXParser::Paren_exprContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitId_expr(MXParser::Id_exprContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitFunction_call_expr(MXParser::Function_call_exprContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitFormatted_string_expr(MXParser::Formatted_string_exprContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitConstant_expr(MXParser::Constant_exprContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitFormatted_string(MXParser::Formatted_stringContext *context) { + throw std::runtime_error("Not implemented"); +} +std::any Visitor::visitConstant(MXParser::ConstantContext *context) { throw std::runtime_error("Not implemented"); } +std::any Visitor::visitType(MXParser::TypeContext *context) { throw std::runtime_error("Not implemented"); }