switch() { } done right.

This commit is contained in:
Pavel Machek 1999-10-28 21:03:36 +00:00
parent c2250f91c7
commit 41be4444f2
6 changed files with 50 additions and 65 deletions

View file

@ -4,12 +4,12 @@
objdir=obj objdir=obj
all depend: all depend tags:
$(MAKE) -C $(objdir) $@ $(MAKE) -C $(objdir) $@
clean: clean:
$(MAKE) -C $(objdir) clean $(MAKE) -C $(objdir) clean
find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name .#* | xargs rm -f find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name ".#*" | xargs rm -f
distclean: clean distclean: clean
rm -rf $(objdir) rm -rf $(objdir)

View file

@ -14,7 +14,7 @@ function callme (int arg1; int arg2;)
case arg1 { case arg1 {
2: print "dva"; print "jeste jednou dva"; 2: print "dva"; print "jeste jednou dva";
[ 3 .. 5 ]: print "tri az pet"; 3 .. 5: print "tri az pet";
else: print "neco jineho"; else: print "neco jineho";
} }
} }
@ -40,8 +40,11 @@ prefix px;
print "Testing prefixes: 1.2.3.4/18 = " px; print "Testing prefixes: 1.2.3.4/18 = " px;
print "Testing pairs: (1,2) = " (1,2); print "Testing pairs: (1,2) = " (1,2);
print "What will this do? " [ 1, 2, 1, 1, 1, 3, 4, 1, 1, 1, 5 ];
print "Testing functions..."; print "Testing functions...";
callme ( 1, 2 ); # callme ( 1, 2 );
callme ( 2, 2 );
callme ( 2, 2 ); callme ( 2, 2 );
callme ( 3, 2 ); callme ( 3, 2 );
callme ( 4, 2 ); callme ( 4, 2 );

View file

@ -43,7 +43,7 @@ CF_DECLS
%type <i> expr bool pxlen datetime %type <i> expr bool pxlen datetime
%nonassoc '=' '<' '>' '~' ELSE IF '.' %nonassoc '=' '<' '>' '~' IF ELSE '.'
%left '+' '-' %left '+' '-'
%left '*' '/' '%' %left '*' '/' '%'
%left '!' %left '!'

View file

@ -11,7 +11,6 @@
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
FIXME: create community lists FIXME: create community lists
FIXME: access to dynamic attributes FIXME: access to dynamic attributes
FIXME: make case faster
*/ */
CF_HDR CF_HDR
@ -37,10 +36,10 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
FILTER FILTER
) )
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body %type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list
%type <f> filter filter_body %type <f> filter filter_body
%type <i> type break_command pair %type <i> type break_command pair
%type <e> set_item set_items %type <e> set_item set_items switch_body
%type <v> set_atom prefix prefix_s ipa %type <v> set_atom prefix prefix_s ipa
%type <s> decls function_params %type <s> decls function_params
@ -191,6 +190,20 @@ set_items:
| set_items ',' set_item { $$ = $3; $$->left = $1; } | set_items ',' set_item { $$ = $3; $$->left = $1; }
; ;
/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */
switch_body: /* EMPTY */ { $$ = NULL; }
| set_item ':' cmds switch_body {
$$ = $1;
$$->data = $3;
$$->left = $4;
}
| ELSE ':' cmds {
$$ = f_new_tree();
$$->from.type = T_VOID;
$$->to.type = T_VOID;
$$->data = $3;
}
;
constant: constant:
CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; } CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
@ -286,23 +299,6 @@ var_list: term {
} }
; ;
/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */
switch_body: /* EMPTY */ { $$ = NULL; }
| term ':' cmds switch_body {
$$ = f_new_inst();
$$->code = 'of';
$$->a1.p = $1;
$$->a2.p = $3;
$$->next = $4;
}
| ELSE ':' cmds {
$$ = f_new_inst();
$$->code = 'el';
$$->a1.p = NULL;
$$->a2.p = $3;
}
;
cmd: cmd:
ifthen { ifthen {
$$ = $1; $$ = $1;
@ -346,9 +342,9 @@ cmd:
} }
| CASE term '{' switch_body '}' { | CASE term '{' switch_body '}' {
$$ = f_new_inst(); $$ = f_new_inst();
$$->code = 'sw'; $$->code = 'SW';
$$->a1.p = $2; $$->a1.p = $2;
$$->a2.p = $4; $$->a2.p = build_tree( $4 );
} }
; ;

View file

@ -54,6 +54,13 @@ struct f_inst *startup_func = NULL;
int int
val_compare(struct f_val v1, struct f_val v2) val_compare(struct f_val v1, struct f_val v2)
{ {
if ((v1.type == T_VOID) && (v2.type == T_VOID))
return 0;
if (v1.type == T_VOID) /* Hack for else */
return -1;
if (v2.type == T_VOID)
return 1;
if (v1.type != v2.type) if (v1.type != v2.type)
return CMP_ERROR; return CMP_ERROR;
switch (v1.type) { switch (v1.type) {
@ -64,7 +71,7 @@ val_compare(struct f_val v1, struct f_val v2)
return 1; return 1;
case T_IP: case T_IP:
return ipa_compare(v1.val.ip, v2.val.ip); return ipa_compare(v1.val.ip, v2.val.ip);
default: return CMP_ERROR; default: { printf( "Error comparing\n" ); return CMP_ERROR; }
} }
} }
@ -114,40 +121,6 @@ static struct rte **f_rte;
static struct f_val interpret(struct f_inst *what); static struct f_val interpret(struct f_inst *what);
static struct f_val
interpret_switch(struct f_inst *what, struct f_val control)
{
struct f_val this, res;
int i;
res.type = T_VOID;
if (!what)
return res;
switch(what->code) {
case 'el':
return interpret(what->a2.p);
case 'of':
this = interpret(what->a1.p);
i = val_compare(control, this);
if (!i)
return interpret(what->a2.p);
if (i==CMP_ERROR) {
i = val_in_range(control, this);
if (i==1)
return interpret(what->a2.p);
if (i==CMP_ERROR)
runtime( "incompatible types in case" );
}
break;
default:
bug( "This can not happen (%x)\n", what->code );
}
return interpret_switch(what->next, control);
}
static struct f_val static struct f_val
interpret(struct f_inst *what) interpret(struct f_inst *what)
{ {
@ -309,9 +282,22 @@ interpret(struct f_inst *what)
ONEARG; ONEARG;
res = interpret(what->a2.p); res = interpret(what->a2.p);
break; break;
case 'sw': /* SWITCH alias CASE */ case 'SW':
ONEARG; ONEARG;
interpret_switch(what->a2.p, v1); {
struct f_tree *t = find_tree(what->a2.p, v1);
if (!t) {
v1.type = T_VOID;
t = find_tree(what->a2.p, v1);
if (!t) {
printf( "No else statement?\n ");
break;
}
}
if (!t->data)
die( "Impossible: no code associated!\n" );
return interpret(t->data);
}
break; break;
case 'iM': /* IP.MASK(val) */ case 'iM': /* IP.MASK(val) */
TWOARGS_C; TWOARGS_C;

View file

@ -73,7 +73,7 @@ struct f_tree *
find_tree(struct f_tree *t, struct f_val val) find_tree(struct f_tree *t, struct f_val val)
{ {
if (!t) if (!t)
return 0; return NULL;
if ((val_compare(t->from, val) != 1) && if ((val_compare(t->from, val) != 1) &&
(val_compare(t->to, val) != -1)) (val_compare(t->to, val) != -1))
return t; return t;