Implement exp1

main
Su Xing 3 years ago
parent ed701d9e4d
commit 5a82467d04

@ -1,28 +0,0 @@
#include <algorithm>
#include <iostream>
using namespace std;
#include "ASTPrinter.h"
#include "SysYParser.h"
any ASTPrinter::visitNumber(SysYParser::NumberContext *ctx) {
cout << ctx->IntConst()->getText();
return nullptr;
}
any ASTPrinter::visitString(SysYParser::StringContext *ctx) {
cout << ctx->String()->getText();
return nullptr;
}
any ASTPrinter::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) {
if (ctx->funcRParam().empty())
return nullptr;
auto numParams = ctx->funcRParam().size();
ctx->funcRParam(0)->accept(this);
for (int i = 1; i < numParams; ++i) {
cout << ", ";
ctx->funcRParam(i)->accept(this);
}
cout << '\n';
return nullptr;
}

@ -1,12 +1,181 @@
#pragma once
#include "SysYBaseVisitor.h"
#include "SysYBaseListener.h"
#include <ostream>
class SysYASTPrinter : public SysYBaseListener {
std::ostream &os;
int indent;
class ASTPrinter : public SysYBaseVisitor {
public:
std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override;
// std::any visitExpAsRParam(SysYParser::ExpAsRParamContext *ctx) override;
// std::any visitStringAsRParam(SysYParser::StringAsRParamContext *ctx) override;
std::any visitNumber(SysYParser::NumberContext *ctx) override;
std::any visitString(SysYParser::StringContext *ctx) override;
};
SysYASTPrinter(std::ostream &os = std::cout) : os(os), indent(0) {}
protected:
void enter(const std::string &name) {
os << std::string(indent, ' ') << name << '\n';
indent += 2;
}
void exit() { indent -= 2; }
public:
virtual void enterModule(SysYParser::ModuleContext * /*ctx*/) override {
enter("module");
}
virtual void enterDecl(SysYParser::DeclContext * /*ctx*/) override {
enter("decl");
}
virtual void enterBtype(SysYParser::BtypeContext * /*ctx*/) override {
enter("btype");
}
// virtual void
// enterConstValue(SysYParser::ConstValueContext * /*ctx*/) override {
// enter("constValue");
// }
virtual void enterVarDef(SysYParser::VarDefContext *ctx) override {
enter("varDef");
}
virtual void enterFunc(SysYParser::FuncContext * /*ctx*/) override {
enter("func");
}
virtual void enterFuncType(SysYParser::FuncTypeContext * /*ctx*/) override {
enter("funcType");
}
virtual void
enterFuncFParams(SysYParser::FuncFParamsContext * /*ctx*/) override {
enter("funcFParams");
}
virtual void
enterFuncFParam(SysYParser::FuncFParamContext * /*ctx*/) override {
enter("funcFParam");
}
virtual void enterBlockStmt(SysYParser::BlockStmtContext * /*ctx*/) override {
enter("blockStmt");
}
virtual void enterBlockItem(SysYParser::BlockItemContext * /*ctx*/) override {
enter("blockIterm");
}
virtual void enterStmt(SysYParser::StmtContext * /*ctx*/) override {
enter("stmt");
}
virtual void
enterAssignStmt(SysYParser::AssignStmtContext * /*ctx*/) override {
enter("assignStmt");
}
virtual void enterExpStmt(SysYParser::ExpStmtContext * /*ctx*/) override {
enter("expStmt");
}
virtual void enterIfStmt(SysYParser::IfStmtContext *ctx) override {
enter("ifStmt " + ctx->getText());
}
virtual void enterWhileStmt(SysYParser::WhileStmtContext * /*ctx*/) override {
enter("whileStmt");
}
virtual void enterBreakStmt(SysYParser::BreakStmtContext * /*ctx*/) override {
enter("break");
}
virtual void
enterContinueStmt(SysYParser::ContinueStmtContext * /*ctx*/) override {
enter("continueStmt");
}
virtual void
enterReturnStmt(SysYParser::ReturnStmtContext * /*ctx*/) override {
enter("returnStmt");
}
virtual void enterEmptyStmt(SysYParser::EmptyStmtContext * /*ctx*/) override {
enter("emptyStmt");
}
virtual void enterRelationExp(SysYParser::RelationExpContext *ctx) override {
enter(std::string("relationExp: ") + ctx->getText());
}
virtual void
enterMultiplicativeExp(SysYParser::MultiplicativeExpContext *ctx) override {
enter(std::string("multiplicativeExp: ") + ctx->getText());
}
virtual void enterCallExp(SysYParser::CallExpContext * ctx) override {
enter("callExp " + ctx->getText());
}
virtual void enterLValueExp(SysYParser::LValueExpContext * /*ctx*/) override {
enter("lValueExp");
}
virtual void enterNumberExp(SysYParser::NumberExpContext * /*ctx*/) override {
enter("numberExp");
}
virtual void enterAndExp(SysYParser::AndExpContext * /*ctx*/) override {
enter("andExp");
}
virtual void enterUnaryExp(SysYParser::UnaryExpContext *ctx) override {
enter(std::string("multiplicativeExp: ") + ctx->getText());
}
virtual void enterParenExp(SysYParser::ParenExpContext * /*ctx*/) override {
enter("parenExp");
}
virtual void enterStringExp(SysYParser::StringExpContext * /*ctx*/) override {
enter("stringExp");
}
virtual void enterOrExp(SysYParser::OrExpContext * /*ctx*/) override {
enter("orExp");
}
virtual void enterAdditiveExp(SysYParser::AdditiveExpContext *ctx) override {
enter(std::string("additiveExp: ") + ctx->getText());
}
virtual void enterEqualExp(SysYParser::EqualExpContext *ctx) override {
enter(std::string("equalExp: ") + ctx->getText());
}
virtual void enterLValue(SysYParser::LValueContext * /*ctx*/) override {
enter("lValue");
}
virtual void enterNumber(SysYParser::NumberContext * /*ctx*/) override {
enter("number");
}
virtual void enterString(SysYParser::StringContext * /*ctx*/) override {
enter("string");
}
virtual void
enterFuncRParams(SysYParser::FuncRParamsContext * /*ctx*/) override {
enter("funcRparams");
}
virtual void enterEveryRule(antlr4::ParserRuleContext *ctx) override {
// os << ctx->getText();
// enter("");
}
virtual void exitEveryRule(antlr4::ParserRuleContext * /*ctx*/) override {
exit();
}
virtual void visitTerminal(antlr4::tree::TerminalNode * /*node*/) override {}
virtual void visitErrorNode(antlr4::tree::ErrorNode * /*node*/) override {}
};

@ -5,6 +5,7 @@ antlr_target(SysYGen SysY.g4
LEXER PARSER
OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VISITOR
LISTENER
)
add_library(SysYParser SHARED ${ANTLR_SysYGen_CXX_OUTPUTS})
@ -13,7 +14,7 @@ target_link_libraries(SysYParser PUBLIC antlr4_shared)
add_executable(sysyc
sysyc.cpp
ASTPrinter.cpp
SysYFormatter.cpp
)
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(sysyc PRIVATE SysYParser)

@ -4,33 +4,165 @@ grammar SysY;
/* Lexer rules */
/*===-------------------------------------------===*/
Comma: ',';
// fragments
fragment Decimal: [0-9];
fragment Octal: [0-7];
fragment Heximal: [0-9a-fA-F];
fragment NonZeroDecimal: [1-9];
// keywords
CONST: 'const';
INT: 'int';
FLOAT: 'float';
VOID: 'void';
IF: 'if';
ELSE: 'else';
WHILE: 'while';
BREAK: 'break';
CONTINUE: 'continue';
RETURN: 'return';
IntConst: NonZeroDecimal Decimal*
| '0' Octal+
| ('0x' | '0X') Heximal+;
// operators
ASSIGN: '=';
ADD: '+';
SUB: '-';
MUL: '*';
DIV: '/';
MODULO: '%';
LT: '<';
GT: '>';
LE: '<=';
GE: '>=';
EQ: '==';
NE: '!=';
AND: '&&';
OR: '||';
NOT: '!';
String: '"' (ESC | .)*? '"';
// punctuations
LPAREN: '(';
RPAREN: ')';
LBRACKET: '[';
RBRACKET: ']';
LBRACE: '{';
RBRACE: '}';
COMMA: ',';
SEMICOLON: ';';
// identifier
fragment ALPHA: [a-zA-Z];
fragment ALPHANUM: [a-zA-Z0-9];
fragment NONDIGIT: [a-zA-Z_];
ID: NONDIGIT (ALPHANUM | '_')*;
// literals
fragment DecDigit: [0-9];
fragment OctDigit: [0-7];
fragment HexDigit: [0-9a-fA-F];
fragment OctPrefix: '0';
fragment HexPrefix: '0' [xX];
fragment NonZeroDecDigit: [1-9];
fragment Sign: [+-];
fragment DecFractional: DecDigit* '.' DecDigit+ | DecDigit+ '.';
fragment Exponent: [eE] Sign? DecDigit+;
fragment DecFloat: DecFractional Exponent? | DecDigit+ Exponent;
fragment HexFractional: HexDigit* '.' HexDigit+ | HexDigit+ '.';
fragment BinExponent: [pP] Sign? DecDigit+;
fragment HexFloat:
HexPrefix HexFractional BinExponent
| HexDigit+ BinExponent;
ILITERAL:
NonZeroDecDigit DecDigit*
| OctPrefix OctDigit*
| HexPrefix HexDigit+;
FLITERAL: DecFloat | HexFloat;
// string
fragment ESC: '\\"' | '\\\\';
STRING: '"' (ESC | .)*? '"';
// white space and comments
WS: [ \t\r\n] -> skip;
LINE_COMMENT: '//' .*? '\r'? '\n' -> skip;
COMMENT: '/*' .*? '*/' -> skip;
LINECOMMENT: '//' .*? '\r'? '\n' -> skip;
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
/*===-------------------------------------------===*/
/* Syntax rules */
/*===-------------------------------------------===*/
funcRParams: funcRParam (Comma funcRParam)* EOF;
module: (decl | func)+;
// constDecl and varDecl shares the same syntax structure, except that constDecl must have constant
// initial values. We combine these two syntax rules, and ensure the constraint above at the
// semantic check phase.
decl: CONST? btype varDef (COMMA varDef)* SEMICOLON;
btype: INT | FLOAT;
varDef: lValue (ASSIGN initValue)?;
initValue:
exp # scalarInitValue
| LBRACE (initValue (COMMA initValue)*)? # arrayInitValue;
func: funcType ID LPAREN funcFParams? RPAREN blockStmt;
funcType: VOID | INT | FLOAT;
funcFParams: funcFParam (COMMA funcFParam)*;
funcFParam:
btype ID (LBRACKET RBRACKET (LBRACKET exp RBRACKET)*)?;
blockStmt: LBRACE blockItem* RBRACE;
blockItem: decl | stmt;
stmt:
assignStmt
| expStmt
| ifStmt
| whileStmt
| breakStmt
| continueStmt
| returnStmt
| blockStmt
| emptyStmt;
assignStmt: lValue ASSIGN exp SEMICOLON;
expStmt: exp SEMICOLON;
ifStmt: IF LPAREN exp RPAREN stmt (ELSE stmt)?;
whileStmt: WHILE LPAREN exp RPAREN stmt;
breakStmt: BREAK SEMICOLON;
continueStmt: CONTINUE SEMICOLON;
returnStmt: RETURN exp? SEMICOLON;
emptyStmt: SEMICOLON;
exp:
LPAREN exp RPAREN # parenExp
| lValue # lValueExp
| number # numberExp
| string # stringExp
| call # callExp
| (ADD | SUB | NOT) exp # unaryExp
| exp (MUL | DIV | MODULO) exp # multiplicativeExp
| exp (ADD | SUB) exp # additiveExp
| exp (LT | GT | LE | GE) exp # relationExp
| exp (EQ | NE) exp # equalExp
| exp AND exp # andExp
| exp OR exp # orExp;
call: ID LPAREN funcRParams? RPAREN;
lValue: ID (LBRACKET exp RBRACKET)*;
number: ILITERAL | FLITERAL;
funcRParam: number # expAsRParam | string # stringAsRParam;
string: STRING;
number: IntConst;
string: String;
funcRParams: exp (COMMA exp)*;

@ -0,0 +1,28 @@
#include <algorithm>
#include <iostream>
using namespace std;
#include "SysYParser.h"
#include "SysYFormatter.h"
// any ASTPrinter::visitNumber(SysYParser::NumberContext *ctx) {
// cout << ctx->IntConst()->getText();
// return nullptr;
// }
// any ASTPrinter::visitString(SysYParser::StringContext *ctx) {
// cout << ctx->String()->getText();
// return nullptr;
// }
// any ASTPrinter::visitFuncRParams(SysYParser::FuncRParamsContext *ctx) {
// if (ctx->funcRParam().empty())
// return nullptr;
// auto numParams = ctx->funcRParam().size();
// ctx->funcRParam(0)->accept(this);
// for (int i = 1; i < numParams; ++i) {
// cout << ", ";
// ctx->funcRParam(i)->accept(this);
// }
// cout << '\n';
// return nullptr;
// }

@ -0,0 +1,334 @@
#pragma once
#include "SysYBaseVisitor.h"
#include "SysYParser.h"
#include <ostream>
class SysYFormatter : public SysYBaseVisitor {
protected:
std::ostream &os;
int indent = 0;
public:
SysYFormatter(std::ostream &os) : os(os), indent(0) {}
protected:
struct Indentor {
static constexpr int TabSize = 2;
int &indent;
Indentor(int &indent) : indent(indent) { indent += TabSize; }
~Indentor() { indent -= TabSize; }
};
std::ostream &space() { return os << std::string(indent, ' '); }
template <typename T>
std::ostream &interleave(const T &container, const std::string sep = ", ") {
auto b = container.begin(), e = container.end();
(*b)->accept(this);
for (b = std::next(b); b != e; b = std::next(b)) {
os << sep;
(*b)->accept(this);
}
return os;
}
public:
// virtual std::any visitModule(SysYParser::ModuleContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any visitBtype(SysYParser::BtypeContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
space();
if (ctx->CONST())
os << ctx->CONST()->getText() << ' ';
ctx->btype()->accept(this);
os << ' ';
interleave(ctx->varDef(), ", ") << ';' << '\n';
return 0;
}
virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
ctx->lValue()->accept(this);
if (ctx->initValue()) {
os << ' ' << '=' << ' ';
ctx->initValue()->accept(this);
}
return 0;
}
virtual std::any
visitArrayInitValue(SysYParser::ArrayInitValueContext *ctx) override {
os << '{';
auto values = ctx->initValue();
if (values.size())
interleave(values, ", ");
os << '}';
return 0;
}
virtual std::any visitFunc(SysYParser::FuncContext *ctx) override {
ctx->funcType()->accept(this);
os << ' ' << ctx->ID()->getText() << '(';
if (ctx->funcFParams())
ctx->funcFParams()->accept(this);
os << ')' << ' ';
ctx->blockStmt()->accept(this);
os << '\n';
return 0;
}
virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any
visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
interleave(ctx->funcFParam(), ", ");
return 0;
}
virtual std::any
visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
ctx->btype()->accept(this);
os << ' ' << ctx->ID()->getText();
if (not ctx->LBRACKET().empty()) {
os << '[';
auto exp = ctx->exp();
if (not exp.empty()) {
os << '[';
interleave(exp, "][") << ']';
}
}
return 0;
}
virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override {
os << '{' << '\n';
{
Indentor indentor(indent);
auto items = ctx->blockItem();
if (not items.empty())
interleave(items, "");
}
space() << ctx->RBRACE()->getText() << '\n';
return 0;
}
// virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx)
// override {
// return visitChildren(ctx);
// }
// virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any
visitAssignStmt(SysYParser::AssignStmtContext *ctx) override {
space();
ctx->lValue()->accept(this);
os << " = ";
ctx->exp()->accept(this);
os << ';' << '\n';
return 0;
}
virtual std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override {
space();
ctx->exp()->accept(this);
os << ';' << '\n';
return 0;
}
void wrapBlock(SysYParser::StmtContext *stmt) {
bool isBlock = stmt->blockStmt();
if (isBlock) {
stmt->accept(this);
} else {
os << "{\n";
{
Indentor indentor(indent);
stmt->accept(this);
}
space() << "}\n";
}
};
virtual std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override {
space();
os << ctx->IF()->getText() << " (";
ctx->exp()->accept(this);
os << ") ";
auto stmt = ctx->stmt();
auto ifStmt = stmt[0];
wrapBlock(ifStmt);
if (stmt.size() == 2) {
auto elseStmt = stmt[1];
wrapBlock(elseStmt);
}
return 0;
}
virtual std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override {
space();
os << ctx->WHILE()->getText() << " (";
ctx->exp()->accept(this);
os << ") ";
wrapBlock(ctx->stmt());
return 0;
}
virtual std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override {
space() << ctx->BREAK()->getText() << ';' << '\n';
return 0;
}
virtual std::any
visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override {
space() << ctx->CONTINUE()->getText() << ';'
<< '\n';
return 0;
}
virtual std::any
visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override {
space() << ctx->RETURN()->getText();
if (ctx->exp()) {
os << ' ';
ctx->exp()->accept(this);
}
os << ';' << '\n';
return 0;
}
// virtual std::any visitEmptyStmt(SysYParser::EmptyStmtContext *ctx)
// override {
// return visitChildren(ctx);
// }
virtual std::any
visitRelationExp(SysYParser::RelationExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op =
ctx->LT() ? "<" : (ctx->LE() ? "<=" : (ctx->GT() ? ">" : ">="));
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any
visitMultiplicativeExp(SysYParser::MultiplicativeExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->MUL() ? "*" : (ctx->DIV() ? "/" : "%");
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
// virtual std::any visitLValueExp(SysYParser::LValueExpContext *ctx) override {
// return visitChildren(ctx);
// }
// virtual std::any visitNumberExp(SysYParser::NumberExpContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any visitAndExp(SysYParser::AndExpContext *ctx) override {
ctx->exp(0)->accept(this);
os << " && ";
ctx->exp(1)->accept(this);
return 0;
}
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
std::string op = ctx->ADD() ? "+" : (ctx->SUB() ? "-" : "!");
os << op;
ctx->exp()->accept(this);
return 0;
}
virtual std::any visitParenExp(SysYParser::ParenExpContext *ctx) override {
os << '(';
ctx->exp()->accept(this);
os << ')';
return 0;
}
virtual std::any visitStringExp(SysYParser::StringExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitOrExp(SysYParser::OrExpContext *ctx) override {
ctx->exp(0)->accept(this);
os << " || ";
ctx->exp(1)->accept(this);
return 0;
}
// virtual std::any visitCallExp(SysYParser::CallExpContext *ctx) override {
// return visitChildren(ctx);
// }
virtual std::any
visitAdditiveExp(SysYParser::AdditiveExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->ADD() ? "+" : "-";
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any visitEqualExp(SysYParser::EqualExpContext *ctx) override {
auto lhs = ctx->exp(0);
auto rhs = ctx->exp(1);
std::string op = ctx->EQ() ? "==" : "!=";
lhs->accept(this);
os << ' ' << op << ' ';
rhs->accept(this);
return 0;
}
virtual std::any visitCall(SysYParser::CallContext *ctx) override {
os << ctx->ID()->getText() << '(';
if (ctx->funcRParams())
ctx->funcRParams()->accept(this);
os << ')';
return 0;
}
virtual std::any visitLValue(SysYParser::LValueContext *ctx) override {
os << ctx->ID()->getText();
auto exp = ctx->exp();
if (not exp.empty()) {
os << '[';
interleave(exp, "][") << ']';
}
return 0;
}
virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any visitString(SysYParser::StringContext *ctx) override {
os << ctx->getText();
return 0;
}
virtual std::any
visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
interleave(ctx->exp(), ", ");
return 0;
}
};

@ -1,12 +1,13 @@
#include "ASTPrinter.h"
#include "tree/ParseTreeWalker.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
using namespace std;
using namespace antlr4;
#include "SysYFormatter.h"
#include "SysYLexer.h"
#include "SysYParser.h"
#include "ASTPrinter.h"
int main(int argc, char **argv) {
if (argc != 2) {
@ -22,10 +23,13 @@ int main(int argc, char **argv) {
SysYLexer lexer(&input);
CommonTokenStream tokens(&lexer);
SysYParser parser(&tokens);
SysYParser::FuncRParamsContext *params = parser.funcRParams();
ASTPrinter printer;
printer.visitFuncRParams(params);
auto module = parser.module();
// tree::ParseTreeWalker walker;
// SysYASTPrinter printer(cout);
// cout << module->getText() << '\n';
// walker.walk(&printer, module);
SysYFormatter formatter(cout);
formatter.visitModule(module);
return EXIT_SUCCESS;
}
Loading…
Cancel
Save