Skip to content

Commit

Permalink
Finish integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Borja Lorente committed May 3, 2017
1 parent 01b9891 commit 824b333
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 49 deletions.
11 changes: 11 additions & 0 deletions examples/Conditionals.grace
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var x := 0;
if (x < 1) {
x := 4;
}

var y := 3;
if (y < 1) {
y := 4;
} else {
y := 6;
}
11 changes: 11 additions & 0 deletions examples/Loops.grace
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var x := 4;
var i := 0;
var j := 0;
while {i < 5} {
while {j < 5} {
x := x + 1;
j := j + 1;
}
j := 0;
i := i + 1;
}
7 changes: 7 additions & 0 deletions grammars/GraceLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ VAR: 'var ';
DEF: 'def ';
PREFIX: 'prefix';
OBJECT: 'object';
IF: 'if';
ELSE: 'else';
WHILE: 'while';

COMMA: ',';
DOT: '.';
Expand All @@ -73,6 +76,10 @@ DIV: '/';
MOD: '%';
POW: '^';
EQUAL: '=';
LESS: '<';
LESS_EQUAL: '<=';
GREATER: '>';
GREATER_EQUAL: '>=';

TRUE: 'true';
FALSE: 'false';
Expand Down
104 changes: 59 additions & 45 deletions grammars/GraceLexer.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,68 @@ VAR=7
DEF=8
PREFIX=9
OBJECT=10
COMMA=11
DOT=12
DELIMITER=13
QUOTE=14
EXCLAMATION=15
RIGHT_ARROW=16
OPEN_PAREN=17
CLOSE_PAREN=18
OPEN_BRACE=19
CLOSE_BRACE=20
OPEN_BRACKET=21
CLOSE_BRACKET=22
CONCAT=23
PLUS=24
MINUS=25
MUL=26
DIV=27
MOD=28
POW=29
EQUAL=30
TRUE=31
FALSE=32
ID=33
IF=11
ELSE=12
WHILE=13
COMMA=14
DOT=15
DELIMITER=16
QUOTE=17
EXCLAMATION=18
RIGHT_ARROW=19
OPEN_PAREN=20
CLOSE_PAREN=21
OPEN_BRACE=22
CLOSE_BRACE=23
OPEN_BRACKET=24
CLOSE_BRACKET=25
CONCAT=26
PLUS=27
MINUS=28
MUL=29
DIV=30
MOD=31
POW=32
EQUAL=33
LESS=34
LESS_EQUAL=35
GREATER=36
GREATER_EQUAL=37
TRUE=38
FALSE=39
ID=40
'method '=5
':='=6
'var '=7
'def '=8
'prefix'=9
'object'=10
','=11
'.'=12
';'=13
'"'=14
'!'=15
'->'=16
'('=17
')'=18
'{'=19
'}'=20
'['=21
']'=22
'++'=23
'+'=24
'-'=25
'*'=26
'/'=27
'%'=28
'^'=29
'='=30
'true'=31
'false'=32
'if'=11
'else'=12
'while'=13
','=14
'.'=15
';'=16
'"'=17
'!'=18
'->'=19
'('=20
')'=21
'{'=22
'}'=23
'['=24
']'=25
'++'=26
'+'=27
'-'=28
'*'=29
'/'=30
'%'=31
'^'=32
'='=33
'<'=34
'<='=35
'>'=36
'>='=37
'true'=38
'false'=39
26 changes: 22 additions & 4 deletions grammars/GraceParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,22 @@ void doAfter() {}
* Parser Rules
*/
program: (statement)*;
statement: expression DELIMITER | declaration | assignment; //| control;
statement: expression DELIMITER | declaration | assignment | control;

assignment : field=identifier VAR_ASSIGN val=expression DELIMITER #SelfAssign
| scope=explicitRequest DOT field=identifier VAR_ASSIGN val=expression DELIMITER #ExplAssign
| scope=implicitRequest DOT field=identifier VAR_ASSIGN val=expression DELIMITER #ImplAssign
;

control : ifThen
| ifThenElse
| whileNode
;

ifThen : IF OPEN_PAREN cond=expression CLOSE_PAREN thn=methodBody;
ifThenElse : IF OPEN_PAREN cond=expression CLOSE_PAREN thn=methodBody ELSE els=methodBody;
whileNode : WHILE OPEN_BRACE cond=expression CLOSE_BRACE body=methodBody;

declaration : variableDeclaration
| constantDeclaration
| methodDeclaration
Expand All @@ -97,15 +106,15 @@ formalParameterList: formalParameter (COMMA formalParameter)*;
formalParameter: identifier;

methodBody: OPEN_BRACE methodBodyLine* CLOSE_BRACE;
methodBodyLine: variableDeclaration | constantDeclaration | expression DELIMITER; //| control;
methodBodyLine: variableDeclaration | constantDeclaration | expression DELIMITER | control | assignment;

// Using left-recursion and implicit operator precendence. ANTLR 4 Reference, page 70
expression : rec=expression op=(MUL | DIV) param=expression #MulDivExp
| rec=expression op=(PLUS | MINUS) param=expression #AddSubExp
| explicitRequest #ExplicitReqExp
| implicitRequest #ImplicitReqExp
| prefix_op rec=expression #PrefixExp
| rec=expression infix_op param=expression #InficExp
| rec=expression infix_op param=expression #InfixExp
| value #ValueExp
;

Expand Down Expand Up @@ -144,5 +153,14 @@ number: INT;
boolean: TRUE | FALSE;
string: QUOTE content=.*? QUOTE;
prefix_op: MINUS | EXCLAMATION;
infix_op: MOD | POW | CONCAT;
infix_op: MOD
| POW
| CONCAT
| LESS
| LESS_EQUAL
| GREATER
| GREATER_EQUAL
| EQUAL EQUAL
| EXCLAMATION EQUAL
;

58 changes: 58 additions & 0 deletions interpreter/src/core/parser/NaylangParserVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ antlrcpp::Any NaylangParserVisitor::visitPrefixExp(GraceParser::PrefixExpContext
return 0;
}

antlrcpp::Any NaylangParserVisitor::visitInfixExp(GraceParser::InfixExpContext *ctx) {
ctx->infix_op()->accept(this);
auto opname = popPartialStr();
ctx->rec->accept(this);
auto rec = popPartialExp();
ctx->param->accept(this);
auto param = popPartialExp();
std::vector<ExpressionPtr> params{param};
auto req = make_node<ExplicitRequestNode>(opname, rec, params, getLine(ctx), getCol(ctx));
pushPartialExp(req);
return 0;
}

antlrcpp::Any NaylangParserVisitor::visitInfix_op(GraceParser::Infix_opContext *ctx) {
pushPartialStr(ctx->getText() + "(_)");
return 0;
}


antlrcpp::Any NaylangParserVisitor::visitNumber(GraceParser::NumberContext *ctx) {
int lastLine = ctx->stop->getLine();
Expand Down Expand Up @@ -422,4 +440,44 @@ antlrcpp::Any NaylangParserVisitor::visitExplAssign(GraceParser::ExplAssignConte
pushPartialStat(assign);
return 0;
}

antlrcpp::Any NaylangParserVisitor::visitIfThen(GraceParser::IfThenContext *ctx) {
ctx->cond->accept(this);
auto cond = popPartialExp();

ctx->thn->accept(this);
auto bodyLength = ctx->thn->methodBodyLine().size();
auto body = popPartialStats(bodyLength);

pushPartialStat(make_node<IfThen>(cond, body));
return 0;
}

antlrcpp::Any NaylangParserVisitor::visitIfThenElse(GraceParser::IfThenElseContext *ctx) {
ctx->cond->accept(this);
auto cond = popPartialExp();

ctx->thn->accept(this);
auto thenLength = ctx->thn->methodBodyLine().size();
auto thenBlock = popPartialStats(thenLength);

ctx->els->accept(this);
auto elsLen = ctx->els->methodBodyLine().size();
auto elseBlock = popPartialStats(elsLen);

pushPartialStat(make_node<IfThenElse>(cond, thenBlock, elseBlock));
return 0;
}

antlrcpp::Any NaylangParserVisitor::visitWhileNode(GraceParser::WhileNodeContext *ctx) {
ctx->cond->accept(this);
auto cond = popPartialExp();

ctx->body->accept(this);
auto bodyLength = ctx->body->methodBodyLine().size();
auto body = popPartialStats(bodyLength);

pushPartialStat(make_node<While>(cond, body));
return 0;
}
}
7 changes: 7 additions & 0 deletions interpreter/src/core/parser/NaylangParserVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@ class NaylangParserVisitor : public GraceParserBaseVisitor {
antlrcpp::Any visitImplAssign(GraceParser::ImplAssignContext *ctx) override;
antlrcpp::Any visitExplAssign(GraceParser::ExplAssignContext *ctx) override;

antlrcpp::Any visitIfThen(GraceParser::IfThenContext *ctx) override;
antlrcpp::Any visitIfThenElse(GraceParser::IfThenElseContext *ctx) override;
antlrcpp::Any visitWhileNode(GraceParser::WhileNodeContext *ctx) override;

antlrcpp::Any visitPrefixExp(GraceParser::PrefixExpContext *ctx) override;
antlrcpp::Any visitPrefix_op(GraceParser::Prefix_opContext *ctx) override;

antlrcpp::Any visitInfixExp(GraceParser::InfixExpContext *ctx) override;
antlrcpp::Any visitInfix_op(GraceParser::Infix_opContext *ctx) override;

antlrcpp::Any visitNumber(GraceParser::NumberContext *ctx) override;
antlrcpp::Any visitString(GraceParser::StringContext *ctx) override;
antlrcpp::Any visitBoolean(GraceParser::BooleanContext *ctx) override;
Expand Down
39 changes: 39 additions & 0 deletions tests/src/core/parser/NaylangParserVisitor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,45 @@ TEST_CASE("Assignment", "[Naylang Parser Visitor]") {
}
}

TEST_CASE("Control Structures") {
SECTION("IfThen") {
auto AST = translate("if (6 < 5) {5;}");
auto it = static_cast<IfThen &>(*(AST[0]));
auto cond = static_cast<ExplicitRequestNode &>(*it.condition());
auto rec = static_cast<NumberLiteral &>(*cond.receiver());
auto param = static_cast<NumberLiteral &>(*cond.params()[0]);
auto five = static_cast<NumberLiteral &>(*it.thenPart()[0]);
REQUIRE(it.thenPart().size() == 1);
REQUIRE(cond.identifier() == "<(_)");
REQUIRE(rec.value() == 6.0);
REQUIRE(param.value() == 5.0);
REQUIRE(five.value() == 5.0);
}

SECTION("IfThenElse") {
auto AST = translate("if (true) {\n 5;\n } else {\n 6;\n }\n");
auto ite = static_cast<IfThenElse &>(*(AST[0]));
auto tr = static_cast<BooleanLiteral &>(*ite.condition());
auto five = static_cast<NumberLiteral &>(*ite.thenPart()[0]);
auto six = static_cast<NumberLiteral &>(*ite.elsePart()[0]);
REQUIRE(ite.thenPart().size() == 1);
REQUIRE(ite.elsePart().size() == 1);
REQUIRE(tr.value());
REQUIRE(five.value() == 5.0);
REQUIRE(six.value() == 6.0);
}

SECTION("While") {
auto AST = translate("while {true} {\n 5;\n }\n");
auto wh = static_cast<While &>(*(AST[0]));
auto tr = static_cast<BooleanLiteral &>(*wh.condition());
auto five = static_cast<NumberLiteral &>(*wh.body()[0]);
REQUIRE(wh.body().size() == 1);
REQUIRE(tr.value());
REQUIRE(five.value() == 5.0);
}
}

GraceAST translate(std::string line) {
ANTLRInputStream stream(line);
GraceLexer lexer(&stream);
Expand Down

0 comments on commit 824b333

Please sign in to comment.