Adds REPEAT and WHILE loop.
This commit is contained in:
parent
908c0e2ff1
commit
cf02215de8
4 changed files with 100 additions and 2 deletions
|
@ -4,7 +4,8 @@ VAR res : INT;
|
|||
PUB main(x : INT) → c : INT
|
||||
BEGIN
|
||||
# factorial(10) → res;
|
||||
fibonacci(7) → res;
|
||||
# fibonacci(7) → res;
|
||||
problem1(1000) → res;
|
||||
END
|
||||
|
||||
PUB factorial(number : INT) → result : INT
|
||||
|
@ -25,3 +26,21 @@ BEGIN
|
|||
ELSE
|
||||
fibonacci(n - 1) + fibonacci(n - 2) → f;
|
||||
END
|
||||
|
||||
# If we list all the natural numbers below 10 that are
|
||||
# multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of
|
||||
# these multiples is 23.
|
||||
# Find the sum of all the multiples of 3 or 5 below 1000.
|
||||
PUB problem1(max : INT) → r : INT | iter : INT
|
||||
BEGIN
|
||||
1 → iter;
|
||||
0 → r;
|
||||
WHILE iter < max DO
|
||||
BEGIN
|
||||
IF (iter % 5) = 0 THEN
|
||||
r + iter → r;
|
||||
ELSEIF (iter % 3) = 0 THEN
|
||||
r + iter → r;
|
||||
iter + 1 → iter;
|
||||
END
|
||||
END
|
||||
|
|
|
@ -55,6 +55,7 @@ FROM { return KW_FROM; }
|
|||
TO { return KW_TO; }
|
||||
UNTIL { return KW_UNTIL; }
|
||||
WHILE { return KW_WHILE; }
|
||||
DO { return KW_DO; }
|
||||
[0-9]+\.[0-9]* { yylval->fval = atof(yytext); return REAL; }
|
||||
[0-9]+ { yylval->ival = atoi(yytext); return INT; }
|
||||
[a-zA-Z0-9']+ { yylval->text = strdup(yytext); return IDENTIFIER; }
|
||||
|
|
|
@ -106,6 +106,7 @@ void yyerror(void *scanner, const char *s);
|
|||
%token KW_TO
|
||||
%token KW_UNTIL
|
||||
%token KW_WHILE
|
||||
%token KW_DO
|
||||
|
||||
%type <type> typeName
|
||||
%type <varDecl> variableDeclaration
|
||||
|
@ -128,6 +129,7 @@ void yyerror(void *scanner, const char *s);
|
|||
%type <instruction> expression
|
||||
%type <instruction> condition
|
||||
%type <instruction> elseIfLoop
|
||||
%type <instruction> loop
|
||||
|
||||
%type <expressions> expressionList
|
||||
|
||||
|
@ -284,11 +286,16 @@ instruction:
|
|||
block { $$ = $1; }
|
||||
| expression SEMICOLON { $$ = $1; }
|
||||
| condition { $$ = $1; }
|
||||
| loop { $$ = $1; }
|
||||
;
|
||||
|
||||
loop:
|
||||
KW_REPEAT instruction { $$ = new RepeatEndlessExpression($2); }
|
||||
| KW_WHILE expression KW_DO instruction { $$ = new RepeatWhileExpression($2, $4); }
|
||||
;
|
||||
|
||||
condition:
|
||||
KW_IF expression KW_THEN instruction elseIfLoop { $$ = new IfExpression($2, $4, $5); }
|
||||
//| KW_IF expression KW_THEN instruction KW_ELSE instruction { $$ = new IfExpression($2, $4, $6); }
|
||||
;
|
||||
|
||||
elseIfLoop:
|
||||
|
|
|
@ -428,4 +428,75 @@ namespace trainscript
|
|||
return Variable::Void;
|
||||
}
|
||||
};
|
||||
|
||||
class RepeatEndlessExpression :
|
||||
public Instruction
|
||||
{
|
||||
public:
|
||||
Instruction *block;
|
||||
|
||||
RepeatEndlessExpression(Instruction *block) :
|
||||
block(block)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->block == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing block.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
Variable result = this->block->execute(context);
|
||||
(void)result;
|
||||
}
|
||||
return Variable::Void;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RepeatWhileExpression :
|
||||
public Instruction
|
||||
{
|
||||
public:
|
||||
Instruction *condition;
|
||||
Instruction *block;
|
||||
|
||||
RepeatWhileExpression(Instruction *condition, Instruction *block) :
|
||||
condition(condition),
|
||||
block(block)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable execute(LocalContext &context) const override {
|
||||
if(this->condition == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing condition.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
if(this->block == nullptr) {
|
||||
if(verbose) printf("REPEAT: missing block.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
Variable cond = this->condition->execute(context);
|
||||
|
||||
if(cond.type != Type::Boolean) {
|
||||
printf("REPEAT: Invalid expression type.\n");
|
||||
return Variable::Invalid;
|
||||
}
|
||||
|
||||
if(cond.boolean == false) {
|
||||
break;
|
||||
}
|
||||
|
||||
this->block->execute(context);
|
||||
}
|
||||
return Variable::Void;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue