Adds first version of IF ... THEN with block or single instruction support.

This commit is contained in:
Felix Queissner 2015-08-10 17:05:58 +02:00
parent 5a6be7e742
commit b5b63b5817
6 changed files with 68 additions and 24 deletions

View file

@ -39,7 +39,8 @@ DISTFILES += \
trainscript/trainscript.l \ trainscript/trainscript.l \
trainscript/file01.ts \ trainscript/file01.ts \
trainscript/Makefile \ trainscript/Makefile \
trainscript/trainscript.y trainscript/trainscript.y \
trainscript/file02.ts
QMAKE_INCDIR = QMAKE_INCDIR =

View file

@ -62,7 +62,7 @@ struct MethodBody
struct MethodDeclaration struct MethodDeclaration
{ {
MethodHeader header; MethodHeader header;
MethodBody *body; trainscript::Instruction *body;
}; };
struct ExpressionList struct ExpressionList

View file

@ -1,8 +1,14 @@
VAR temp : BOOL; VAR res : INT;
PUB main(x : INT) c : INT PUB main(x : INT) c : INT
BEGIN BEGIN
(x =/= c) temp; factorial(10) res;
x c; END
PUB factorial(number : INT) result : INT
BEGIN
1 result;
IF number > 1 THEN
number * factorial(number - 1) result;
END END

View file

@ -47,6 +47,7 @@ BOOL { return KW_BOOL; }
BEGIN { return KW_BEGIN; } BEGIN { return KW_BEGIN; }
END { return KW_END; } END { return KW_END; }
IF { return KW_IF; } IF { return KW_IF; }
THEN { return KW_THEN; }
ELSE { return KW_ELSE; } ELSE { return KW_ELSE; }
REPEAT { return KW_REPEAT; } REPEAT { return KW_REPEAT; }
FROM { return KW_FROM; } FROM { return KW_FROM; }

View file

@ -98,6 +98,7 @@ void yyerror(void *scanner, const char *s);
%token KW_END %token KW_END
%token KW_IF %token KW_IF
%token KW_THEN
%token KW_ELSE %token KW_ELSE
%token KW_REPEAT %token KW_REPEAT
%token KW_FROM %token KW_FROM
@ -112,7 +113,7 @@ void yyerror(void *scanner, const char *s);
%type <method> method %type <method> method
%type <methodHeader> methodDeclaration %type <methodHeader> methodDeclaration
%type <body> block %type <instruction> block
%type <body> body %type <body> body
%type <local> argument %type <local> argument
@ -141,20 +142,8 @@ input:
| input method { | input method {
using namespace trainscript; using namespace trainscript;
auto *mod = context->module; auto *mod = context->module;
Block *body = new Block();
// Translate body here Method *method = new Method(mod, $2.body);
MethodBody *mb = $2.body;
while(mb) {
if(mb->instruction != nullptr) {
body->instructions.push_back(mb->instruction);
} else {
printf("invalid instruction in %s\n", $2.header.name);
}
mb = mb->next;
}
Method *method = new Method(mod, body);
method->isPublic = $2.header.isPublic; method->isPublic = $2.header.isPublic;
if($2.header.returnValue) { if($2.header.returnValue) {
method->returnValue = std::pair<std::string, Variable>( method->returnValue = std::pair<std::string, Variable>(
@ -184,12 +173,22 @@ method:
; ;
block: block:
KW_BEGIN body KW_END { $$ = $2; } KW_BEGIN body KW_END {
auto *block = new Block();
MethodBody *mb = $2;
while(mb) {
if(mb->instruction != nullptr) {
block->instructions.push_back(mb->instruction);
}
mb = mb->next;
}
$$ = block;
}
; ;
body: body:
%empty { $$ = nullptr; } %empty { $$ = nullptr; }
| body instruction SEMICOLON { | body instruction {
auto *body = new MethodBody(); auto *body = new MethodBody();
body->indentation = 0; body->indentation = 0;
body->instruction = $2; body->instruction = $2;
@ -277,7 +276,8 @@ argument:
; ;
instruction: instruction:
expression { $$ = $1; } expression SEMICOLON { $$ = $1; }
| KW_IF expression KW_THEN instruction { $$ = new ConditionExpression($2, $4); }
; ;
expression: expression:

View file

@ -169,13 +169,13 @@ namespace trainscript
{ {
public: public:
Module *module; Module *module;
Block *block; Instruction *block;
bool isPublic; bool isPublic;
std::vector<std::pair<std::string, Variable>> arguments; std::vector<std::pair<std::string, Variable>> arguments;
std::map<std::string, Variable> locals; std::map<std::string, Variable> locals;
std::pair<std::string, Variable> returnValue; std::pair<std::string, Variable> returnValue;
Method(Module *module, Block *block) : module(module), block(block) Method(Module *module, Instruction *block) : module(module), block(block)
{ {
} }
@ -391,4 +391,40 @@ namespace trainscript
return OP(left, right); return OP(left, right);
} }
}; };
class ConditionExpression :
public Instruction
{
public:
Instruction *condition;
Instruction *block;
ConditionExpression(Instruction *condition, Instruction *block) :
condition(condition),
block(block)
{
}
Variable execute(LocalContext &context) const override {
if(this->condition == nullptr) {
if(verbose) printf("IF: missing condition.\n");
return Variable::Invalid;
}
if(this->block == nullptr) {
return Variable::Void;
}
Variable result = this->condition->execute(context);
if(result.type != Type::Boolean) {
if(verbose) printf("IF: Invalid condition type.\n");
return Variable::Invalid;
}
if(result.boolean && (this->block != nullptr)) {
this->block->execute(context);
}
return Variable::Void;
}
};
} }