mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 04:30:43 +00:00
implement break and continue. only loops covered for now, but that's because
switch isn't implemented yet
This commit is contained in:
parent
552a486d87
commit
133ce647fb
3 changed files with 69 additions and 26 deletions
|
@ -14,7 +14,7 @@ X move the chained funcion support out of emit_function_expr into
|
||||||
X pre- and post- increment operators (++ and --)
|
X pre- and post- increment operators (++ and --)
|
||||||
I gut out old parser
|
I gut out old parser
|
||||||
o switch/case, for any type
|
o switch/case, for any type
|
||||||
o break/continue keywords for switch() and for(;;)
|
X break/continue keywords for switch() and for(;;)
|
||||||
o quaternion type. Tricky: requires 4 word args/return
|
o quaternion type. Tricky: requires 4 word args/return
|
||||||
o CSE optimisations
|
o CSE optimisations
|
||||||
X full scoping
|
X full scoping
|
||||||
|
|
|
@ -220,6 +220,8 @@ static keyword_t keywords[] = {
|
||||||
{"if", IF, 0, PROG_ID_VERSION},
|
{"if", IF, 0, PROG_ID_VERSION},
|
||||||
{"else", ELSE, 0, PROG_ID_VERSION},
|
{"else", ELSE, 0, PROG_ID_VERSION},
|
||||||
{"for", FOR, 0, PROG_ID_VERSION},
|
{"for", FOR, 0, PROG_ID_VERSION},
|
||||||
|
{"break", BREAK, 0, PROG_ID_VERSION},
|
||||||
|
{"continue", CONTINUE, 0, PROG_ID_VERSION},
|
||||||
{"NIL", NIL, 0, PROG_ID_VERSION},
|
{"NIL", NIL, 0, PROG_ID_VERSION},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -103,13 +103,14 @@ typedef struct {
|
||||||
%token <vector_val> VECTOR_VAL
|
%token <vector_val> VECTOR_VAL
|
||||||
%token <quaternion_val> QUATERNION_VAL
|
%token <quaternion_val> QUATERNION_VAL
|
||||||
|
|
||||||
%token LOCAL RETURN WHILE DO IF ELSE FOR ELIPSIS NIL
|
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
|
||||||
%token <type> TYPE
|
%token <type> TYPE
|
||||||
|
|
||||||
%type <type> type maybe_func
|
%type <type> type maybe_func
|
||||||
%type <def> param param_list def_item def_list def_name
|
%type <def> param param_list def_item def_list def_name
|
||||||
%type <expr> const opt_expr expr arg_list
|
%type <expr> const opt_expr expr arg_list
|
||||||
%type <expr> statement statements statement_block
|
%type <expr> statement statements statement_block
|
||||||
|
%type <expr> break_label continue_label
|
||||||
%type <function> begin_function
|
%type <function> begin_function
|
||||||
%type <def_list> save_inits
|
%type <def_list> save_inits
|
||||||
|
|
||||||
|
@ -122,6 +123,8 @@ def_t *current_def;
|
||||||
def_t param_scope;
|
def_t param_scope;
|
||||||
function_t *current_func;
|
function_t *current_func;
|
||||||
expr_t *local_expr;
|
expr_t *local_expr;
|
||||||
|
expr_t *break_label;
|
||||||
|
expr_t *continue_label;
|
||||||
|
|
||||||
def_t *pr_scope; // the function being parsed, or NULL
|
def_t *pr_scope; // the function being parsed, or NULL
|
||||||
string_t s_file; // filename for function definition
|
string_t s_file; // filename for function definition
|
||||||
|
@ -404,38 +407,59 @@ statement
|
||||||
{
|
{
|
||||||
$$ = return_expr (current_func, 0);
|
$$ = return_expr (current_func, 0);
|
||||||
}
|
}
|
||||||
| WHILE '(' expr ')' save_inits statement
|
| BREAK ';'
|
||||||
|
{
|
||||||
|
if (break_label)
|
||||||
|
$$ = new_unary_expr ('g', break_label);
|
||||||
|
else
|
||||||
|
$$ = error (0, "break outside of loop or switch");
|
||||||
|
}
|
||||||
|
| CONTINUE ';'
|
||||||
|
{
|
||||||
|
if (continue_label)
|
||||||
|
$$ = new_unary_expr ('g', continue_label);
|
||||||
|
else
|
||||||
|
$$ = error (0, "continue outside of loop");
|
||||||
|
}
|
||||||
|
| WHILE break_label continue_label '(' expr ')' save_inits statement
|
||||||
{
|
{
|
||||||
expr_t *l1 = new_label_expr ();
|
expr_t *l1 = new_label_expr ();
|
||||||
expr_t *l2 = new_label_expr ();
|
expr_t *l2 = break_label;
|
||||||
expr_t *e;
|
expr_t *e;
|
||||||
|
|
||||||
restore_local_inits ($5);
|
restore_local_inits ($7);
|
||||||
free_local_inits ($5);
|
free_local_inits ($7);
|
||||||
|
|
||||||
$$ = new_block_expr ();
|
$$ = new_block_expr ();
|
||||||
|
|
||||||
e = new_binary_expr ('n', test_expr ($3, 1), l2);
|
e = new_binary_expr ('n', test_expr ($5, 1), l2);
|
||||||
e->line = $3->line;
|
e->line = $5->line;
|
||||||
e->file = $3->file;
|
e->file = $5->file;
|
||||||
append_expr ($$, e);
|
append_expr ($$, e);
|
||||||
append_expr ($$, l1);
|
append_expr ($$, l1);
|
||||||
append_expr ($$, $6);
|
append_expr ($$, $8);
|
||||||
e = new_binary_expr ('i', test_expr ($3, 1), l1);
|
append_expr ($$, continue_label);
|
||||||
e->line = $3->line;
|
e = new_binary_expr ('i', test_expr ($5, 1), l1);
|
||||||
e->file = $3->file;
|
e->line = $5->line;
|
||||||
|
e->file = $5->file;
|
||||||
append_expr ($$, e);
|
append_expr ($$, e);
|
||||||
append_expr ($$, l2);
|
append_expr ($$, l2);
|
||||||
|
break_label = $2;
|
||||||
|
continue_label = $3;
|
||||||
}
|
}
|
||||||
| DO statement WHILE '(' expr ')' ';'
|
| DO break_label continue_label statement WHILE '(' expr ')' ';'
|
||||||
{
|
{
|
||||||
expr_t *l1 = new_label_expr ();
|
expr_t *l1 = new_label_expr ();
|
||||||
|
|
||||||
$$ = new_block_expr ();
|
$$ = new_block_expr ();
|
||||||
|
|
||||||
append_expr ($$, l1);
|
append_expr ($$, l1);
|
||||||
append_expr ($$, $2);
|
append_expr ($$, $4);
|
||||||
append_expr ($$, new_binary_expr ('i', test_expr ($5, 1), l1));
|
append_expr ($$, continue_label);
|
||||||
|
append_expr ($$, new_binary_expr ('i', test_expr ($7, 1), l1));
|
||||||
|
append_expr ($$, break_label);
|
||||||
|
break_label = $2;
|
||||||
|
continue_label = $3;
|
||||||
}
|
}
|
||||||
| LOCAL type
|
| LOCAL type
|
||||||
{
|
{
|
||||||
|
@ -503,25 +527,28 @@ statement
|
||||||
free_local_inits (else_ini);
|
free_local_inits (else_ini);
|
||||||
free_local_inits ($<def_list>8);
|
free_local_inits ($<def_list>8);
|
||||||
}
|
}
|
||||||
| FOR '(' opt_expr ';' opt_expr ';' opt_expr ')' save_inits statement
|
| FOR break_label continue_label '(' opt_expr ';' opt_expr ';' opt_expr ')' save_inits statement
|
||||||
{
|
{
|
||||||
expr_t *l1 = new_label_expr ();
|
expr_t *l1 = new_label_expr ();
|
||||||
expr_t *l2 = new_label_expr ();
|
expr_t *l2 = break_label;
|
||||||
|
|
||||||
restore_local_inits ($9);
|
restore_local_inits ($11);
|
||||||
free_local_inits ($9);
|
free_local_inits ($11);
|
||||||
|
|
||||||
$$ = new_block_expr ();
|
$$ = new_block_expr ();
|
||||||
|
|
||||||
append_expr ($$, $3);
|
append_expr ($$, $5);
|
||||||
if ($5)
|
if ($7)
|
||||||
append_expr ($$, new_binary_expr ('n', test_expr ($5, 1), l2));
|
append_expr ($$, new_binary_expr ('n', test_expr ($7, 1), l2));
|
||||||
append_expr ($$, l1);
|
append_expr ($$, l1);
|
||||||
append_expr ($$, $10);
|
append_expr ($$, $12);
|
||||||
append_expr ($$, $7);
|
append_expr ($$, continue_label);
|
||||||
|
append_expr ($$, $9);
|
||||||
if ($5)
|
if ($5)
|
||||||
append_expr ($$, new_binary_expr ('i', test_expr ($5, 1), l1));
|
append_expr ($$, new_binary_expr ('i', test_expr ($7, 1), l1));
|
||||||
append_expr ($$, l2);
|
append_expr ($$, l2);
|
||||||
|
break_label = $2;
|
||||||
|
continue_label = $3;
|
||||||
}
|
}
|
||||||
| expr ';'
|
| expr ';'
|
||||||
{
|
{
|
||||||
|
@ -529,6 +556,20 @@ statement
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
break_label
|
||||||
|
: /* empty */
|
||||||
|
{
|
||||||
|
$$ = break_label;
|
||||||
|
break_label = new_label_expr ();
|
||||||
|
}
|
||||||
|
|
||||||
|
continue_label
|
||||||
|
: /* empty */
|
||||||
|
{
|
||||||
|
$$ = continue_label;
|
||||||
|
continue_label = new_label_expr ();
|
||||||
|
}
|
||||||
|
|
||||||
save_inits
|
save_inits
|
||||||
: /* empty */
|
: /* empty */
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue