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
|
PUB main(x : INT) → c : INT
|
||||||
BEGIN
|
BEGIN
|
||||||
# factorial(10) → res;
|
# factorial(10) → res;
|
||||||
fibonacci(7) → res;
|
# fibonacci(7) → res;
|
||||||
|
problem1(1000) → res;
|
||||||
END
|
END
|
||||||
|
|
||||||
PUB factorial(number : INT) → result : INT
|
PUB factorial(number : INT) → result : INT
|
||||||
|
@ -25,3 +26,21 @@ BEGIN
|
||||||
ELSE
|
ELSE
|
||||||
fibonacci(n - 1) + fibonacci(n - 2) → f;
|
fibonacci(n - 1) + fibonacci(n - 2) → f;
|
||||||
END
|
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; }
|
TO { return KW_TO; }
|
||||||
UNTIL { return KW_UNTIL; }
|
UNTIL { return KW_UNTIL; }
|
||||||
WHILE { return KW_WHILE; }
|
WHILE { return KW_WHILE; }
|
||||||
|
DO { return KW_DO; }
|
||||||
[0-9]+\.[0-9]* { yylval->fval = atof(yytext); return REAL; }
|
[0-9]+\.[0-9]* { yylval->fval = atof(yytext); return REAL; }
|
||||||
[0-9]+ { yylval->ival = atoi(yytext); return INT; }
|
[0-9]+ { yylval->ival = atoi(yytext); return INT; }
|
||||||
[a-zA-Z0-9']+ { yylval->text = strdup(yytext); return IDENTIFIER; }
|
[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_TO
|
||||||
%token KW_UNTIL
|
%token KW_UNTIL
|
||||||
%token KW_WHILE
|
%token KW_WHILE
|
||||||
|
%token KW_DO
|
||||||
|
|
||||||
%type <type> typeName
|
%type <type> typeName
|
||||||
%type <varDecl> variableDeclaration
|
%type <varDecl> variableDeclaration
|
||||||
|
@ -128,6 +129,7 @@ void yyerror(void *scanner, const char *s);
|
||||||
%type <instruction> expression
|
%type <instruction> expression
|
||||||
%type <instruction> condition
|
%type <instruction> condition
|
||||||
%type <instruction> elseIfLoop
|
%type <instruction> elseIfLoop
|
||||||
|
%type <instruction> loop
|
||||||
|
|
||||||
%type <expressions> expressionList
|
%type <expressions> expressionList
|
||||||
|
|
||||||
|
@ -284,11 +286,16 @@ instruction:
|
||||||
block { $$ = $1; }
|
block { $$ = $1; }
|
||||||
| expression SEMICOLON { $$ = $1; }
|
| expression SEMICOLON { $$ = $1; }
|
||||||
| condition { $$ = $1; }
|
| condition { $$ = $1; }
|
||||||
|
| loop { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
loop:
|
||||||
|
KW_REPEAT instruction { $$ = new RepeatEndlessExpression($2); }
|
||||||
|
| KW_WHILE expression KW_DO instruction { $$ = new RepeatWhileExpression($2, $4); }
|
||||||
;
|
;
|
||||||
|
|
||||||
condition:
|
condition:
|
||||||
KW_IF expression KW_THEN instruction elseIfLoop { $$ = new IfExpression($2, $4, $5); }
|
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:
|
elseIfLoop:
|
||||||
|
|
|
@ -428,4 +428,75 @@ namespace trainscript
|
||||||
return Variable::Void;
|
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