grammar plsm; @parser::header { #include "AST/AST.h" #include "Utils.h" #include #include using namespace plsm::utils; using namespace plsm::ast; } @parser::members { std::string filename, sourceText; void setFileName(const std::string &filename) { this->filename = filename; } void setSourceText(const std::string &sourceText) { this->sourceText = sourceText; } inline SourceRange getSourceRange(antlr4::ParserRuleContext *ctx) { auto start = ctx->start; auto stop = getCurrentToken(); auto startPos = std::pair(start->getLine(), start->getCharPositionInLine()); auto stopPos = std::pair(stop->getLine(), stop->getCharPositionInLine()); auto text = sourceText.substr( start->getStartIndex(), stop->getStartIndex() - start->getStartIndex()); text = boost::trim_copy(text); // std::cout << "text: `" << text << "`" << std::endl; return SourceRange(filename, text, startPos, stopPos); } } module returns[std::unique_ptr ast]: (stmts += topLevelStmt)* EOF { std::vector> stmts; for (auto &stmt : $ctx->stmts) { stmts.push_back(std::move(stmt->ast)); } $ast = std::make_unique(getSourceRange($ctx), "default", std::vector>(), std::move(stmts)); }; topLevelStmt returns[std::unique_ptr ast]: varDecl { $ast = ptrcast($ctx->varDecl()->ast); } | fnDecl { $ast = ptrcast($ctx->fnDecl()->ast); }; block returns[std::unique_ptr ast]: (stmts += stmt)* { std::vector> stmts; for (auto &stmt : $ctx->stmts) { stmts.push_back(std::move(stmt->ast)); } $ast = std::make_unique(getSourceRange($ctx), std::move(stmts)); }; singleStmtBlock returns[std::unique_ptr ast]: stmt { std::vector> stmts; stmts.push_back(std::move($ctx->stmt()->ast)); $ast = std::make_unique(getSourceRange($ctx), std::move(stmts)); }; stmt returns[std::unique_ptr ast]: exprStmt { $ast = ptrcast($ctx->exprStmt()->ast); } | varDecl { $ast = ptrcast($ctx->varDecl()->ast); } | retStmt { $ast = ptrcast($ctx->retStmt()->ast); } | assignStmt { $ast = ptrcast($ctx->assignStmt()->ast); } | implDeclAssignStmt { $ast = ptrcast($ctx->implDeclAssignStmt()->ast); } | ifStmt { $ast = ptrcast($ctx->ifStmt()->ast); } | whileStmt { $ast = ptrcast($ctx->whileStmt()->ast); }; whileStmt returns[std::unique_ptr ast]: 'while' '(' condition = expr ')' ( '{' block '}' | singleStmtBlock ) { std::unique_ptr body; if ($ctx->block()) body = std::move($ctx->block()->ast); else body = std::move($ctx->singleStmtBlock()->ast); $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(body)); }; ifStmt returns[std::unique_ptr ast]: 'if' '(' condition = expr ')' ( '{' ifBlock = block '}' | ifSingleBlock = singleStmtBlock ) ( 'else' ( '{' elseBlock = block '}' | elseSingleBlock = singleStmtBlock ) )? { std::unique_ptr ifBody; if ($ctx->ifBlock) ifBody = std::move($ctx->ifBlock->ast); else ifBody = std::move($ctx->ifSingleBlock->ast); std::unique_ptr elseBody; if ($ctx->elseBlock) elseBody = std::move($ctx->elseBlock->ast); else if ($ctx->elseSingleBlock) elseBody = std::move($ctx->elseSingleBlock->ast); else elseBody = std::make_unique(SourceRange::unknown(), std::vector>()); $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->condition->ast), std::move(ifBody), std::move(elseBody)); }; implDeclAssignStmt returns[std::unique_ptr ast]: IDENTIFIER ':=' expr { // TODO }; assignStmt returns[std::unique_ptr ast]: lval = expr '=' rval = expr ';' { $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->lval->ast), std::move($ctx->rval->ast)); }; retStmt returns[std::unique_ptr ast]: 'ret' expr ';' { $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->expr()->ast)); }; fnDecl returns[std::unique_ptr ast]: 'fun' name = IDENTIFIER '(' ( params += fnParam (',' params += fnParam)* )? ')' typeName '{' block '}' { auto name = $ctx->name->getText(); std::vector> params; for (auto ¶m : $ctx->params) { params.push_back(std::move(param->ast)); } $ast = std::make_unique(getSourceRange($ctx), name, std::move(params), std::move($ctx->typeName()->ast), std::move($ctx->block()->ast)); }; fnParam returns[std::unique_ptr ast]: IDENTIFIER typeName { $ast = std::make_unique(getSourceRange($ctx), $ctx->IDENTIFIER()->getText(), std::move($ctx->typeName()->ast)); }; varDecl returns[std::unique_ptr ast]: 'var' IDENTIFIER ':' typeName ';' { auto name = $ctx->IDENTIFIER()->getText(); $ast = std::make_unique(getSourceRange($ctx), name, std::move($ctx->typeName()->ast)); }; exprStmt returns[std::unique_ptr ast]: expr ';' { $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->expr()->ast)); }; expr returns[std::unique_ptr ast]: value = binaryExpr { $ast = std::move($ctx->value->ast); }; binaryExpr returns[std::unique_ptr ast]: value = unaryExpr { $ast = std::move($ctx->value->ast); } | lhs = binaryExpr op = ('*' | '/' | '%') rhs = binaryExpr { auto opText = $ctx->op->getText(); BinOp op; if (opText == "*") op = BinOp::MUL; if (opText == "/") op = BinOp::DIV; if (opText == "%") op = BinOp::MOD; auto binExpr = std::make_unique(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast)); $ast = ptrcast(binExpr); } | lhs = binaryExpr op = ('+' | '-') rhs = binaryExpr { auto opText = $ctx->op->getText(); BinOp op; if (opText == "+") op = BinOp::ADD; if (opText == "-") op = BinOp::SUB; auto binExpr = std::make_unique(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast)); $ast = ptrcast(binExpr); } | operand = binaryExpr 'as' typeName { auto castExpr = std::make_unique(getSourceRange($ctx), std::move($ctx->operand->ast), std::move($ctx->typeName()->ast)); $ast = ptrcast(castExpr); } | lhs = binaryExpr op = ( '==' | '!=' | '>=' | '<=' | '>' | '<' ) rhs = binaryExpr { auto opText = $ctx->op->getText(); BinOp op; if (opText == "==") op = BinOp::EQ; if (opText == "!=") op = BinOp::NE; if (opText == ">=") op = BinOp::GE; if (opText == "<=") op = BinOp::LE; if (opText == ">") op = BinOp::GT; if (opText == "<") op = BinOp::LT; auto binExpr = std::make_unique(getSourceRange($ctx), op, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast)); $ast = ptrcast(binExpr); } | lhs = binaryExpr '&&' rhs = binaryExpr { auto binExpr = std::make_unique(getSourceRange($ctx), BinOp::AND, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast)); $ast = ptrcast(binExpr); } | lhs = binaryExpr '||' rhs = binaryExpr { auto binExpr = std::make_unique(getSourceRange($ctx), BinOp::OR, std::move($ctx->lhs->ast), std::move($ctx->rhs->ast)); $ast = ptrcast(binExpr); }; unaryExpr returns[std::unique_ptr ast]: factorExpr { $ast = ptrcast($ctx->factorExpr()->ast); } | functionCall { $ast = ptrcast($ctx->functionCall()->ast); } | '!' unaryExpr { auto unExpr = std::make_unique(getSourceRange($ctx), UnOp::NOT, std::move($ctx->unaryExpr()->ast)); $ast = ptrcast(unExpr); } | '+' unaryExpr { auto unExpr = std::make_unique(getSourceRange($ctx), UnOp::POS, std::move($ctx->unaryExpr()->ast)); $ast = ptrcast(unExpr); } | '-' unaryExpr { auto unExpr = std::make_unique(getSourceRange($ctx), UnOp::NEG, std::move($ctx->unaryExpr()->ast)); $ast = ptrcast(unExpr); }; factorExpr returns[std::unique_ptr ast]: IDENTIFIER { auto id = std::make_unique(getSourceRange($ctx), $ctx->IDENTIFIER()->getText()); $ast = ptrcast(id); } | INT { auto text = $ctx->INT()->getText(); int64_t value; if (!text.rfind("0x", 0)) value = std::strtol(text.substr(2).data(), NULL, 16); else if (!text.rfind("0o", 0)) value = std::strtol(text.substr(2).data(), NULL, 8); else if (!text.rfind("0b", 0)) value = std::strtol(text.substr(2).data(), NULL, 2); else value = std::strtol(text.data(), NULL, 10); auto val = std::make_unique(getSourceRange($ctx), value); $ast = ptrcast(val); } | FLOAT { auto text = $ctx->FLOAT()->getText(); if (text.at(text.size() - 1) == '.') text += "0"; if (text.at(0) == '0') text = "0" + text; double value = std::strtod(text.data(), NULL); auto val = std::make_unique(getSourceRange($ctx), value); $ast = ptrcast(val); } | BOOL { auto text = $ctx->BOOL()->getText(); auto val = std::make_unique(getSourceRange($ctx), text == "true" ? 1 : 0); $ast = ptrcast(val); } | '(' expr ')' { $ast = std::move($ctx->expr()->ast); }; functionCall returns[std::unique_ptr ast]: callee = factorExpr '(' (args += expr (',' args += expr)*)? ')' { std::vector> args; for (auto &arg : $ctx->args) { args.push_back(std::move(arg->ast)); } $ast = std::make_unique(getSourceRange($ctx), std::move($ctx->callee->ast), std::move(args)); }; typeName returns[std::unique_ptr ast]: IDENTIFIER { auto text = $ctx->IDENTIFIER()->getText(); auto named = std::make_unique(getSourceRange($ctx), text); $ast = ptrcast(named); }; INT: [0-9]+ | '0x' [0-9a-fA-F]+ | '0o' [0-7]+ | '0b' [01]+; FLOAT: [0-9]+ '.' | [0-9]* '.' [0-9]+; BOOL: 'true' | 'false'; IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; WHITESPACE: [ \r\n\t]+ -> skip;