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/file01.ts \
trainscript/Makefile \
trainscript/trainscript.y
trainscript/trainscript.y \
trainscript/file02.ts
QMAKE_INCDIR =

View file

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

View file

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

View file

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

View file

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

View file

@ -169,13 +169,13 @@ namespace trainscript
{
public:
Module *module;
Block *block;
Instruction *block;
bool isPublic;
std::vector<std::pair<std::string, Variable>> arguments;
std::map<std::string, Variable> locals;
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);
}
};
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;
}
};
}