File grammar.y changed (mode: 100644) (index 382ef50..ebd5e33) |
... |
... |
funccall: rid LPAREN exprlistcompl RPAREN { |
294 |
294 |
sprintf(ebuf, "Undeclared function %s", $1.str); |
sprintf(ebuf, "Undeclared function %s", $1.str); |
295 |
295 |
getsuggestions($1.str, ebuf, 1, &functions); |
getsuggestions($1.str, ebuf, 1, &functions); |
296 |
296 |
yyerrorex(3, ebuf); |
yyerrorex(3, ebuf); |
297 |
|
$$.ty = gNull; |
|
|
297 |
|
$$.ty = gAny; |
298 |
298 |
} else { |
} else { |
299 |
299 |
if (inconstant && !(fd->isconst)) { |
if (inconstant && !(fd->isconst)) { |
300 |
300 |
char ebuf[1024]; |
char ebuf[1024]; |
|
... |
... |
funccall: rid LPAREN exprlistcompl RPAREN { |
315 |
315 |
sprintf(ebuf, "Undeclared function %s", $1.str); |
sprintf(ebuf, "Undeclared function %s", $1.str); |
316 |
316 |
getsuggestions($1.str, ebuf, 1, &functions); |
getsuggestions($1.str, ebuf, 1, &functions); |
317 |
317 |
yyerrorex(3, ebuf); |
yyerrorex(3, ebuf); |
318 |
|
$$.ty = gNull; |
|
|
318 |
|
$$.ty = gAny; |
319 |
319 |
} else if (inconstant && !(fd->isconst)) { |
} else if (inconstant && !(fd->isconst)) { |
320 |
320 |
char ebuf[1024]; |
char ebuf[1024]; |
321 |
321 |
sprintf(ebuf, "Call to non-constant function %s in constant function", $1.str); |
sprintf(ebuf, "Call to non-constant function %s in constant function", $1.str); |
322 |
322 |
yyerrorex(3, ebuf); |
yyerrorex(3, ebuf); |
323 |
|
$$.ty = gNull; |
|
|
323 |
|
$$.ty = gAny; |
324 |
324 |
} else { |
} else { |
325 |
325 |
if (fd == fCurrent && fCurrent) |
if (fd == fCurrent && fCurrent) |
326 |
326 |
yyerrorex(3, "Recursive function calls are not permitted in local declarations"); |
yyerrorex(3, "Recursive function calls are not permitted in local declarations"); |
|
... |
... |
funcdefn: NEWLINE |
389 |
389 |
| statement { yyerrorex(0, "Statement outside of function"); } |
| statement { yyerrorex(0, "Statement outside of function"); } |
390 |
390 |
; |
; |
391 |
391 |
|
|
392 |
|
funcdefncore: funcbegin localblock codeblock funcend { if(retval != gNothing) { if ($3.ty == gAny || $3.ty == gNone) yyerrorline(1, lineno - 1, "Missing return"); else if (returnbug) canconvertreturn($3.ty, retval, -1); } } |
|
|
392 |
|
funcdefncore: funcbegin localblock codeblock funcend { |
|
393 |
|
if(retval != gNothing) { |
|
394 |
|
if ($3.ty == gAny || $3.ty == gNone) |
|
395 |
|
yyerrorline(1, lineno - 1, "Missing return"); |
|
396 |
|
else if (returnbug) |
|
397 |
|
canconvertreturn($3.ty, retval, -1); |
|
398 |
|
} |
|
399 |
|
} |
393 |
400 |
| funcbegin localblock codeblock {yyerrorex(0, "Missing endfunction"); clear(¶ms); clear(&locals); clear(&initialized); curtab = &globals;} |
| funcbegin localblock codeblock {yyerrorex(0, "Missing endfunction"); clear(¶ms); clear(&locals); clear(&initialized); curtab = &globals;} |
394 |
401 |
; |
; |
395 |
402 |
|
|
|
... |
... |
funcbegin: FUNCTION rid TAKES optparam_list returnorreturns opttype { |
480 |
487 |
} |
} |
481 |
488 |
; |
; |
482 |
489 |
|
|
483 |
|
codeblock: /* empty */ {$$.ty = gAny;} |
|
484 |
|
| statement codeblock { if($2.ty == gAny) $$.ty = $1.ty; else $$.ty = $2.ty;} |
|
|
490 |
|
codeblock: /* empty */ { $$.ty = gNull; } |
|
491 |
|
| statement codeblock { |
|
492 |
|
if($2.ty == gNull) |
|
493 |
|
$$.ty = $1.ty; |
|
494 |
|
else |
|
495 |
|
$$.ty = $2.ty; |
|
496 |
|
} |
485 |
497 |
; |
; |
486 |
498 |
|
|
487 |
|
statement: NEWLINE {$$.ty = gAny;} |
|
|
499 |
|
statement: NEWLINE { $$.ty = gNull; } |
488 |
500 |
| CALL funccall NEWLINE{ $$.ty = gNone;} |
| CALL funccall NEWLINE{ $$.ty = gNone;} |
489 |
|
| IF expr THEN NEWLINE codeblock elsifseq elseseq ENDIF NEWLINE { canconvert($2.ty, gBoolean, -1); $$.ty = combinetype($6.ty!=gAny?combinetype($5.ty, $6.ty):$5.ty, $7.ty);} |
|
|
501 |
|
/*1 2 3 4 5 6 7 8 9 */ |
|
502 |
|
| IF expr THEN NEWLINE codeblock elsifseq elseseq ENDIF NEWLINE { |
|
503 |
|
canconvert($2.ty, gBoolean, -1); |
|
504 |
|
$5.ty = $5.ty == gNull ? gNone : $5.ty; |
|
505 |
|
$6.ty = $6.ty == gNull ? gNull : $6.ty; |
|
506 |
|
$7.ty = $7.ty == gNull ? gNone : $7.ty; |
|
507 |
|
$$.ty = combinetype($5.ty, combinetype($6.ty, $7.ty)); |
|
508 |
|
} |
490 |
509 |
| SET rid EQUALS expr NEWLINE { if (getVariable($2.str)->isarray) { |
| SET rid EQUALS expr NEWLINE { if (getVariable($2.str)->isarray) { |
491 |
510 |
char ebuf[1024]; |
char ebuf[1024]; |
492 |
511 |
sprintf(ebuf, "Index missing for array variable %s", $2.str); |
sprintf(ebuf, "Index missing for array variable %s", $2.str); |
|
... |
... |
statement: NEWLINE {$$.ty = gAny;} |
508 |
527 |
| SET rid LBRACKET expr RBRACKET EQUALS expr NEWLINE{ |
| SET rid LBRACKET expr RBRACKET EQUALS expr NEWLINE{ |
509 |
528 |
const struct typeandname *tan = getVariable($2.str); |
const struct typeandname *tan = getVariable($2.str); |
510 |
529 |
if (tan->ty != gAny) { |
if (tan->ty != gAny) { |
511 |
|
canconvert($4.ty, gInteger, -1); $$.ty = gNone; |
|
|
530 |
|
canconvert($4.ty, gInteger, -1); |
|
531 |
|
$$.ty = gNone; |
512 |
532 |
if (!tan->isarray) { |
if (!tan->isarray) { |
513 |
533 |
char ebuf[1024]; |
char ebuf[1024]; |
514 |
534 |
sprintf(ebuf, "%s is not an array", $2.str); |
sprintf(ebuf, "%s is not an array", $2.str); |
|
... |
... |
statement: NEWLINE {$$.ty = gAny;} |
522 |
542 |
| loopstart NEWLINE codeblock loopend NEWLINE {$$.ty = $3.ty;} |
| loopstart NEWLINE codeblock loopend NEWLINE {$$.ty = $3.ty;} |
523 |
543 |
| loopstart NEWLINE codeblock {$$.ty = $3.ty; yyerrorex(0, "Missing endloop");} |
| loopstart NEWLINE codeblock {$$.ty = $3.ty; yyerrorex(0, "Missing endloop");} |
524 |
544 |
| EXITWHEN expr NEWLINE { canconvert($2.ty, gBoolean, -1); if (!inloop) yyerrorline(0, lineno - 1, "Exitwhen outside of loop"); $$.ty = gNone;} |
| EXITWHEN expr NEWLINE { canconvert($2.ty, gBoolean, -1); if (!inloop) yyerrorline(0, lineno - 1, "Exitwhen outside of loop"); $$.ty = gNone;} |
525 |
|
| RETURN expr NEWLINE { $$.ty = $2.ty; if(retval == gNothing) yyerrorline(1, lineno - 1, "Cannot return value from function that returns nothing"); else if (!returnbug) canconvertreturn($2.ty, retval, 0); } |
|
526 |
|
| RETURN NEWLINE { if (retval != gNothing) yyerrorline(1, lineno - 1, "Return nothing in function that should return value"); $$.ty = gNone;} |
|
|
545 |
|
| RETURN expr NEWLINE { |
|
546 |
|
$$.ty = $2.ty; |
|
547 |
|
if(retval == gNothing) |
|
548 |
|
yyerrorline(1, lineno - 1, "Cannot return value from function that returns nothing"); |
|
549 |
|
else if (!returnbug) |
|
550 |
|
canconvertreturn($2.ty, retval, 0); |
|
551 |
|
} |
|
552 |
|
| RETURN NEWLINE { |
|
553 |
|
if (retval != gNothing) |
|
554 |
|
yyerrorline(1, lineno - 1, "Return nothing in function that should return value"); |
|
555 |
|
$$.ty = gAny; |
|
556 |
|
} |
527 |
557 |
| DEBUG statement {$$.ty = gNone;} |
| DEBUG statement {$$.ty = gNone;} |
528 |
|
| IF expr THEN NEWLINE codeblock elsifseq elseseq {canconvert($2.ty, gBoolean, 0); $$.ty = combinetype($6.ty!=gAny?combinetype($5.ty, $6.ty):$5.ty, $7.ty); yyerrorex(0, "Missing endif");} |
|
529 |
|
| IF expr NEWLINE{canconvert($2.ty, gBoolean, -1); $$.ty = gAny; yyerrorex(0, "Missing then or non valid expression");} |
|
|
558 |
|
/*1 2 3 4 5 6 7 */ |
|
559 |
|
| IF expr THEN NEWLINE codeblock elsifseq elseseq { |
|
560 |
|
canconvert($2.ty, gBoolean, -1); |
|
561 |
|
$5.ty = $5.ty == gNull ? gNone : $5.ty; |
|
562 |
|
$6.ty = $6.ty == gNull ? gNull : $6.ty; |
|
563 |
|
$7.ty = $7.ty == gNull ? gNone : $7.ty; |
|
564 |
|
$$.ty = combinetype($5.ty, combinetype($6.ty, $7.ty)); |
|
565 |
|
yyerrorex(0, "Missing endif"); |
|
566 |
|
} |
|
567 |
|
| IF expr NEWLINE { |
|
568 |
|
canconvert($2.ty, gBoolean, -1); |
|
569 |
|
$$.ty = gAny; |
|
570 |
|
yyerrorex(0, "Missing then or non valid expression"); |
|
571 |
|
} |
530 |
572 |
| SET funccall NEWLINE{$$.ty = gNone; yyerrorline(0, lineno - 1, "Call expected instead of set");} |
| SET funccall NEWLINE{$$.ty = gNone; yyerrorline(0, lineno - 1, "Call expected instead of set");} |
531 |
573 |
| lvardecl {yyerrorex(0, "Local declaration after first statement");} |
| lvardecl {yyerrorex(0, "Local declaration after first statement");} |
532 |
574 |
| error {$$.ty = gNone; } |
| error {$$.ty = gNone; } |
|
... |
... |
loopstart: LOOP {inloop++;} |
538 |
580 |
loopend: ENDLOOP {inloop--;} |
loopend: ENDLOOP {inloop--;} |
539 |
581 |
; |
; |
540 |
582 |
|
|
541 |
|
elseseq: /* empty */ {$$.ty = gNone;} |
|
542 |
|
| ELSE NEWLINE codeblock {$$.ty = $3.ty;} |
|
|
583 |
|
elseseq: /* empty */ { $$.ty = gNull; } |
|
584 |
|
| ELSE NEWLINE codeblock { |
|
585 |
|
if($3.ty == gNull) { |
|
586 |
|
$$.ty = gNone; |
|
587 |
|
} else { |
|
588 |
|
$$.ty = $3.ty; |
|
589 |
|
} |
|
590 |
|
} |
543 |
591 |
; |
; |
544 |
592 |
|
|
545 |
|
elsifseq: /* empty */ {$$.ty = gAny;} |
|
546 |
|
| ELSEIF expr THEN NEWLINE codeblock elsifseq { canconvert($2.ty, gBoolean, -1); $$.ty = $6.ty!=gAny?combinetype($5.ty, $6.ty):$5.ty;} |
|
|
593 |
|
elsifseq: /* empty */ { $$.ty = gNull; } |
|
594 |
|
/* 1 2 3 4 5 6 */ |
|
595 |
|
| ELSEIF expr THEN NEWLINE codeblock elsifseq { |
|
596 |
|
canconvert($2.ty, gBoolean, -1); |
|
597 |
|
if($6.ty == gNull){ |
|
598 |
|
$$.ty = $5.ty == gNull ? gNone : $5.ty; |
|
599 |
|
}else{ |
|
600 |
|
$$.ty = $5.ty == gNull ? gNone : combinetype($5.ty, $6.ty); |
|
601 |
|
} |
|
602 |
|
} |
547 |
603 |
; |
; |
548 |
604 |
|
|
549 |
605 |
optparam_list: param_list { $$.pl = $1.pl; } |
optparam_list: param_list { $$.pl = $1.pl; } |
|
... |
... |
type: primtype { $$.ty = $1.ty; } |
779 |
835 |
sprintf(buf, "Undefined type %s", $1.str); |
sprintf(buf, "Undefined type %s", $1.str); |
780 |
836 |
getsuggestions($1.str, buf, 1, &types); |
getsuggestions($1.str, buf, 1, &types); |
781 |
837 |
yyerrorex(3, buf); |
yyerrorex(3, buf); |
782 |
|
$$.ty = gNull; |
|
|
838 |
|
$$.ty = gAny; |
783 |
839 |
} |
} |
784 |
840 |
else |
else |
785 |
841 |
$$.ty = lookup(&types, $1.str); |
$$.ty = lookup(&types, $1.str); |
File misc.c changed (mode: 100644) (index 4a5ad04..bb467c3) |
... |
... |
struct hashtable *curtab; |
40 |
40 |
struct typenode *retval, *retcheck; |
struct typenode *retval, *retcheck; |
41 |
41 |
const char *curfile; |
const char *curfile; |
42 |
42 |
struct typenode *gInteger, *gReal, *gBoolean, *gString, *gCode, *gHandle, *gNothing, *gNull, *gAny, *gNone, *gCodeReturnsBoolean, *gCodeReturnsNoBoolean; |
struct typenode *gInteger, *gReal, *gBoolean, *gString, *gCode, *gHandle, *gNothing, *gNull, *gAny, *gNone, *gCodeReturnsBoolean, *gCodeReturnsNoBoolean; |
|
43 |
|
struct typenode *gEmpty; |
43 |
44 |
struct funcdecl *fCurrent; |
struct funcdecl *fCurrent; |
44 |
45 |
|
|
45 |
46 |
void addPrimitiveType(const char *name, struct typenode **toSave) |
void addPrimitiveType(const char *name, struct typenode **toSave) |
|
... |
... |
void showtypenode(const struct typenode *td) |
321 |
322 |
extends = ebuf; |
extends = ebuf; |
322 |
323 |
} |
} |
323 |
324 |
*/ |
*/ |
324 |
|
printf("%s%s", td->typename, extends); |
|
|
325 |
|
printf("%s %s \n", td->typename, extends); |
325 |
326 |
} |
} |
326 |
327 |
|
|
327 |
328 |
void showfuncdecl(struct funcdecl *fd) |
void showfuncdecl(struct funcdecl *fd) |
|
... |
... |
int canconvertreturn(const struct typenode *ufrom, const struct typenode *uto, c |
497 |
498 |
struct typenode *combinetype(const struct typenode *n1, const struct typenode *n2) { |
struct typenode *combinetype(const struct typenode *n1, const struct typenode *n2) { |
498 |
499 |
if ((n1 == gNone) || (n2 == gNone)) return gNone; |
if ((n1 == gNone) || (n2 == gNone)) return gNone; |
499 |
500 |
if (n1 == n2) return n1; |
if (n1 == n2) return n1; |
500 |
|
if (n1 == gNull) |
|
|
501 |
|
if (n1 == gNull || n1 == gAny) |
501 |
502 |
return n2; |
return n2; |
502 |
|
if (n2 == gNull) |
|
|
503 |
|
if (n2 == gNull || n2 == gAny) |
503 |
504 |
return n1; |
return n1; |
504 |
505 |
n1 = getPrimitiveAncestor(n1); |
n1 = getPrimitiveAncestor(n1); |
505 |
506 |
n2 = getPrimitiveAncestor(n2); |
n2 = getPrimitiveAncestor(n2); |
506 |
507 |
if (n1 == n2) return n1; |
if (n1 == n2) return n1; |
507 |
|
if (n1 == gNull) |
|
|
508 |
|
if (n1 == gNull || n1 == gAny) |
508 |
509 |
return n2; |
return n2; |
509 |
|
if (n2 == gNull) |
|
|
510 |
|
if (n2 == gNull || n2 == gAny) |
510 |
511 |
return n1; |
return n1; |
511 |
512 |
if ((n1 == gInteger) && (n2 == gReal)) |
if ((n1 == gInteger) && (n2 == gReal)) |
512 |
513 |
return gReal; |
return gReal; |