Adds first version of IF ... THEN with block or single instruction support.
This commit is contained in:
parent
5a6be7e742
commit
b5b63b5817
6 changed files with 68 additions and 24 deletions
|
@ -39,7 +39,8 @@ DISTFILES += \
|
|||
trainscript/trainscript.l \
|
||||
trainscript/file01.ts \
|
||||
trainscript/Makefile \
|
||||
trainscript/trainscript.y
|
||||
trainscript/trainscript.y \
|
||||
trainscript/file02.ts
|
||||
|
||||
QMAKE_INCDIR =
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ struct MethodBody
|
|||
struct MethodDeclaration
|
||||
{
|
||||
MethodHeader header;
|
||||
MethodBody *body;
|
||||
trainscript::Instruction *body;
|
||||
};
|
||||
|
||||
struct ExpressionList
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue