/*
lang.y : the parser.
(c) 2007-2008 Fernando Iazeolla
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
%{
#include
#include
#include
#include "lang.h"
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id_var(char *s);
nodeType *id_word(char *s);
nodeType *id_string(char *s);
nodeType *con(int value);
void freeNode(nodeType *p);
struct _var* ex(nodeType *p);
int yylex(void);
void yyerror(char *s);
//int sym[26]; /* symbol table */
%}
%union {
int iValue; /* integer value */
char *sVar; /* symbol table variable */
char *sWord; /* internal variable */
char *sStruct; /*struct*/
nodeType *nPtr; /* node pointer */
};
%token INTEGER
%token VARIABLE
%token WORD
%token FILENAME
%token STRING
%token WHILE IF PRINT QUIT SAVE LOAD INFO TYPE FORCE SIZEOF FLUSH RELOAD FILE_BEGIN FILE_END
%token REFRESH SHIFT MOVE REALLOC HELP INJECT NEW SHOW CLOSE DUMP GROUTH SHRINK
%token ADDHD RMHD LEN MOVERPOS MOVERNEG EXTRACT
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS STRUCT STRUCT1 STRUCTW STRUCTE OFFSET OFFSETE OFFSET_ROOT
%type stmt expr stmt_list filename ivar Tivar Offset TOffset
%%
program:
function { /*exit(-)*/; }
;
function:
function stmt { ex($2); freeNode($2); }
| /* NULL */
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = $1; }
| PRINT '%' WORD expr ';' {$$=opr(PRINT,2,id_word($3),$4);}
| PRINT expr ';' { $$ = opr(PRINT, 2,NULL, $2); }
| VARIABLE '=' expr ';' { $$ = opr('=', 2, id_var($1), $3); }
| ivar '=' expr ';' { $$ = opr('=', 2, $1, $3); }
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); }
| IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); }
| IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, $3, $5, $7); }
| '{' stmt_list '}' { $$ = $2; }
| QUIT {$$= opr(QUIT,2,NULL,NULL);}
| SAVE {$$=opr(SAVE,2,NULL,NULL);}
| LOAD filename {$$=opr(LOAD,1,$2);}
| LOAD '(' filename ')' {$$=opr(LOAD,1,$3);}
| INFO {$$=opr(INFO,2,NULL,NULL);}
| TYPE {$$=opr(TYPE,2,NULL,NULL);}
| FORCE STRING {$$=opr(FORCE,2,id_string($2),NULL);}
| FORCE '(' STRING ')' {$$=opr(FORCE,2,id_string($3),NULL);}
| SIZEOF {$$=opr(QUIT,2,NULL,NULL);}
| FLUSH {$$=opr(FLUSH,2,NULL,NULL);}
| REFRESH {$$=opr(REFRESH,2,NULL,NULL);}
| RELOAD {$$=opr(RELOAD,2,NULL,NULL);}
| SHIFT {$$=opr(QUIT,2,NULL,NULL);}
| MOVE '(' expr ',' expr ',' expr ')' {$$=opr(MOVE,3,$3,$5,$7);}
| MOVE '(' expr ',' '+' expr ',' expr ')' {$$=opr(MOVERPOS,3,$3,$6,$8);}
| MOVE '(' expr ',' '-' expr ',' expr ')' {$$=opr(MOVERNEG,3,$3,$6,$8);}
| HELP {$$=opr(QUIT,2,NULL,NULL);}
| INJECT '(' expr ',' expr ')' {$$=opr(INJECT,4,$3,$5,NULL,NULL);}
| INJECT '(' expr ',' expr ',' expr ')' {$$=opr(INJECT,4,$3,$5,$7,NULL);}
| INJECT '(' expr ',' expr ',' expr ',' expr ')' {$$=opr(INJECT,4,$3,$5,$7,$9);}
| SHOW {$$=opr(QUIT,2,NULL,NULL);}
| CLOSE {$$=opr(CLOSE,2,NULL,NULL);}
| DUMP '%' WORD expr ';' {$$=opr(DUMP,2,id_word($3),$4);}
| DUMP expr ';' {$$=opr(DUMP,2,NULL,$2);}
| GROUTH expr ';' {$$=opr(GROUTH,1,$2);}
| SHRINK expr ';' {$$=opr(SHRINK,1,$2);}
| ADDHD '(' STRING ')' {$$=opr(ADDHD,4,id_string($3),NULL,NULL,NULL);}
| ADDHD '(' STRING ',' expr ')' {$$=opr(ADDHD,4,id_string($3),$5,NULL,NULL);}
| ADDHD '(' STRING ',' expr ',' STRING ')' {$$=opr(ADDHD,4,id_string($3),$5,id_string($7),NULL);}
| ADDHD '(' STRING ',' expr ',' STRING ',' STRING ')' {$$=opr(ADDHD,4,id_string($3),$5,id_string($7),id_string($9));}
| RMHD '(' STRING ',' expr ')' {$$=opr(RMHD,4,id_string($3),$5,NULL,NULL);}
| RMHD '(' STRING ',' expr ',' STRING ')' {$$=opr(RMHD,4,id_string($3),$5,id_string($7),NULL);}
| RMHD '(' STRING ',' expr ',' STRING ',' STRING ')' {$$=opr(RMHD,4,id_string($3),$5,id_string($7),id_string($9));}
| NEW {$$=opr(NEW,2,NULL,NULL);}
| NEW filename {$$=opr(NEW,2,$2,NULL);}
| NEW '(' filename ')' {$$=opr(NEW,2,$3,NULL);}
| LEN expr ';' {$$=opr(LEN,1,$2);}
| EXTRACT '(' expr ',' expr ',' STRING ')' {$$=opr(EXTRACT,3,$3,$5,id_string($7));}
;
stmt_list:
stmt { $$ = $1; }
| stmt_list stmt { $$ = opr(';', 2, $1, $2); }
;
expr:
INTEGER { $$ = con($1); }
| VARIABLE { $$ = id_var($1); }
| ivar { $$ =$1; }
| FILE_BEGIN {$$=con(get_offset("FILE_BEGIN",'.'));}
| FILE_END {$$=con(get_offset("FILE_END",'.'));}
| FILE_END Offset {$$=opr(OFFSET_ROOT,2,$2,id_word("e"));}
| FILE_BEGIN Offset {$$=opr(OFFSET_ROOT,2,$2,id_word("b"));}
| FILENAME { $$ =id_word($1); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); }
| expr '+' expr { $$ = opr('+', 2, $1, $3); }
| expr '-' expr { $$ = opr('-', 2, $1, $3); }
| expr '*' expr { $$ = opr('*', 2, $1, $3); }
| expr '/' expr { $$ = opr('/', 2, $1, $3); }
| expr '<' expr { $$ = opr('<', 2, $1, $3); }
| expr '>' expr { $$ = opr('>', 2, $1, $3); }
| expr GE expr { $$ = opr(GE, 2, $1, $3); }
| expr LE expr { $$ = opr(LE, 2, $1, $3); }
| expr NE expr { $$ = opr(NE, 2, $1, $3); }
| expr EQ expr { $$ = opr(EQ, 2, $1, $3); }
| '(' expr ')' { $$ = $2; }
| STRING {$$=id_string($1);}
;
filename:
FILENAME {$$=id_word($1);}
| WORD {$$=id_word($1);}
;
ivar:
Tivar {$$=$1;}
| Tivar '-' '>' ivar {$$=opr(STRUCT,2,$1,$4);}
;
Tivar:
WORD '(' WORD ')' {$$=opr(STRUCTW,2,id_word($1),id_word($3));}
| WORD '[' expr ']' {$$=opr(STRUCTE,2,id_word($1),$3);}
| WORD {$$=opr(STRUCT1,1,id_word($1));}
;
Offset:
TOffset '-' '>' Offset {$$=opr(OFFSET,2,$1,$4);}
| TOffset {$$=opr(OFFSET,2,$1,NULL);}
;
TOffset:
// WORD '(' WORD ')' {$$=opr(OFFSETW,2,id_word($1),id_word($3));}
WORD '[' expr ']' {$$=opr(OFFSETE,2,id_word($1),$3);}
| WORD {$$=id_word($1);}
;
%%
#define SIZEOF_NODETYPE ((char *)&p->con - (char *)p)
nodeType *con(int value) {
nodeType *p;
size_t nodeSize;
/* allocate node */
nodeSize = SIZEOF_NODETYPE + sizeof(conNodeType);
if ((p = malloc(nodeSize)) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeCon;
p->con.value = value;
return p;
}
nodeType *id_var(char *s) {
nodeType *p;
size_t nodeSize;
/* allocate node */
nodeSize = SIZEOF_NODETYPE + sizeof(idNodeType);
if ((p = malloc(nodeSize)) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeVar;
p->id.s = s;
return p;
}
nodeType *id_word(char *s) {
nodeType *p;
size_t nodeSize;
/* allocate node */
nodeSize = SIZEOF_NODETYPE + sizeof(idNodeType);
if ((p = malloc(nodeSize)) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeWord;
p->id.s = s;
return p;
}
nodeType *id_string(char *s) {
nodeType *p;
size_t nodeSize;
/* allocate node */
nodeSize = SIZEOF_NODETYPE + sizeof(idNodeType);
if ((p = malloc(nodeSize)) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeString;
p->id.s = s;
return p;
}
nodeType *opr(int oper, int nops, ...) {
va_list ap;
nodeType *p;
size_t nodeSize;
int i;
/* allocate node */
nodeSize = SIZEOF_NODETYPE + sizeof(oprNodeType) +
(nops - 1) * sizeof(nodeType*);
if ((p = malloc(nodeSize)) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeOpr;
p->opr.oper = oper;
p->opr.nops = nops;
va_start(ap, nops);
for (i = 0; i < nops; i++)
p->opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
return p;
}
void freeNode(nodeType *p) {
int i;
if (!p) return;
if (p->type == typeOpr) {
for (i = 0; i < p->opr.nops; i++)
freeNode(p->opr.op[i]);
}
free (p);
}
void yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
//int main(void) {
// yyparse();
// return 0;
//}