2005-07-01 04:29:18 +00:00
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2005-07-18 02:03:41 +00:00
|
|
|
Expression* lastExp = 0;
|
|
|
|
|
2005-07-01 04:29:18 +00:00
|
|
|
#define YYERROR_VERBOSE 1
|
|
|
|
|
2005-09-20 15:17:16 +00:00
|
|
|
/* dump Expression stack during parsing? */
|
|
|
|
#define DEBUG_EXP 0
|
|
|
|
/* #define DEBUG_EXP 1 */
|
|
|
|
|
2005-07-01 04:29:18 +00:00
|
|
|
int yylex();
|
|
|
|
char *yytext;
|
|
|
|
|
|
|
|
void yyerror(char *e) {
|
2005-09-20 15:17:16 +00:00
|
|
|
//if(DEBUG_EXP) fprintf(stderr, "%s at token \"%s\"\n", e, yytext);
|
|
|
|
if(DEBUG_EXP) fprintf(stderr, "%s\n", e);
|
OK, we no longer segfault on parse error.
However, we do leak memory: yyparse() happily allocates Expressions as
it parses, but when it hits a parse error, it doesn't return a valid
pointer to the top of the Expression tree. From what I can tell, the
so-called Expression* result is the int value of the last lexer token
cast to an Expression* (due to yacc's use of a union).
I know how to avoid the leak: we need to keep a vector of Expression
pointers in YaccParser. If there's a parse error, yyerror() can delete
all the Expressions using the vector. If not, we clear the vector (er,
calling .clear() on a vector doesn't delete all its elements, too,
does it?). Every time yacc says "$$ = new WhateverExpression", it also
should vector.push_back($$).
Will implement this tomorrow; am getting tired & flaky.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@655 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2005-07-15 03:47:26 +00:00
|
|
|
errMsg = e;
|
2005-07-23 21:16:57 +00:00
|
|
|
|
|
|
|
// be extra paranoid about deletion
|
|
|
|
if(lastExp && dynamic_cast<Expression*>(lastExp))
|
2005-07-18 02:03:41 +00:00
|
|
|
delete lastExp;
|
2005-07-23 21:16:57 +00:00
|
|
|
|
|
|
|
lastExp = 0;
|
2005-07-01 04:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
2005-07-13 02:54:13 +00:00
|
|
|
%union {
|
|
|
|
int val;
|
2005-07-14 15:13:58 +00:00
|
|
|
char *equate;
|
2005-07-18 23:50:28 +00:00
|
|
|
CPUDEBUG_INT_METHOD cpuMethod;
|
2005-07-19 00:05:23 +00:00
|
|
|
TIADEBUG_INT_METHOD tiaMethod;
|
2005-07-13 02:54:13 +00:00
|
|
|
Expression *exp;
|
2005-07-21 03:26:59 +00:00
|
|
|
char *function;
|
2005-07-13 02:54:13 +00:00
|
|
|
}
|
|
|
|
|
2005-07-14 15:13:58 +00:00
|
|
|
/* Terminals */
|
2005-07-13 02:54:13 +00:00
|
|
|
%token <val> NUMBER
|
2005-07-16 23:46:37 +00:00
|
|
|
%token <val> ERR
|
2005-07-14 15:13:58 +00:00
|
|
|
%token <equate> EQUATE
|
2005-07-18 23:50:28 +00:00
|
|
|
%token <cpuMethod> CPU_METHOD
|
2005-07-19 00:05:23 +00:00
|
|
|
%token <tiaMethod> TIA_METHOD
|
2005-07-21 03:26:59 +00:00
|
|
|
%token <function> FUNCTION
|
2005-07-14 15:13:58 +00:00
|
|
|
|
|
|
|
/* Non-terminals */
|
|
|
|
%type <exp> expression
|
|
|
|
|
|
|
|
/* Operator associativity and precedence */
|
2005-07-01 04:29:18 +00:00
|
|
|
%left '-' '+'
|
|
|
|
%left '*' '/' '%'
|
|
|
|
%left LOG_OR
|
|
|
|
%left LOG_AND
|
2005-07-13 04:49:19 +00:00
|
|
|
%left LOG_NOT
|
2005-07-01 04:29:18 +00:00
|
|
|
%left '|' '^'
|
|
|
|
%left '&'
|
|
|
|
%left SHR SHL
|
2005-07-12 21:50:43 +00:00
|
|
|
%nonassoc '<' '>' GTE LTE NE EQ
|
2005-07-15 01:20:11 +00:00
|
|
|
%nonassoc DEREF
|
2005-07-12 21:50:43 +00:00
|
|
|
%nonassoc UMINUS
|
2005-07-19 01:31:37 +00:00
|
|
|
%nonassoc '['
|
2005-07-01 04:29:18 +00:00
|
|
|
|
2005-07-13 02:54:13 +00:00
|
|
|
|
2005-07-01 04:29:18 +00:00
|
|
|
%%
|
2005-09-20 15:17:16 +00:00
|
|
|
statement: expression { if(DEBUG_EXP) fprintf(stderr, "\ndone\n"); result.exp = $1; }
|
2005-07-01 04:29:18 +00:00
|
|
|
;
|
|
|
|
|
2005-09-20 15:17:16 +00:00
|
|
|
expression: expression '+' expression { if(DEBUG_EXP) fprintf(stderr, " +"); $$ = new PlusExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '-' expression { if(DEBUG_EXP) fprintf(stderr, " -"); $$ = new MinusExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '*' expression { if(DEBUG_EXP) fprintf(stderr, " *"); $$ = new MultExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '/' expression { if(DEBUG_EXP) fprintf(stderr, " /"); $$ = new DivExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '%' expression { if(DEBUG_EXP) fprintf(stderr, " %%"); $$ = new ModExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '&' expression { if(DEBUG_EXP) fprintf(stderr, " &"); $$ = new BinAndExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '|' expression { if(DEBUG_EXP) fprintf(stderr, " |"); $$ = new BinOrExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '^' expression { if(DEBUG_EXP) fprintf(stderr, " ^"); $$ = new BinXorExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '<' expression { if(DEBUG_EXP) fprintf(stderr, " <"); $$ = new LessExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression '>' expression { if(DEBUG_EXP) fprintf(stderr, " >"); $$ = new GreaterExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression GTE expression { if(DEBUG_EXP) fprintf(stderr, " >="); $$ = new GreaterEqualsExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression LTE expression { if(DEBUG_EXP) fprintf(stderr, " <="); $$ = new LessEqualsExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression NE expression { if(DEBUG_EXP) fprintf(stderr, " !="); $$ = new NotEqualsExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression EQ expression { if(DEBUG_EXP) fprintf(stderr, " =="); $$ = new EqualsExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression SHR expression { if(DEBUG_EXP) fprintf(stderr, " >>"); $$ = new ShiftRightExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression SHL expression { if(DEBUG_EXP) fprintf(stderr, " <<"); $$ = new ShiftLeftExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression LOG_OR expression { if(DEBUG_EXP) fprintf(stderr, " ||"); $$ = new LogOrExpression($1, $3); lastExp = $$; }
|
|
|
|
| expression LOG_AND expression { if(DEBUG_EXP) fprintf(stderr, " &&"); $$ = new LogAndExpression($1, $3); lastExp = $$; }
|
|
|
|
| '-' expression %prec UMINUS { if(DEBUG_EXP) fprintf(stderr, " U-"); $$ = new UnaryMinusExpression($2); lastExp = $$; }
|
|
|
|
| '~' expression %prec UMINUS { if(DEBUG_EXP) fprintf(stderr, " ~"); $$ = new BinNotExpression($2); lastExp = $$; }
|
|
|
|
| '!' expression %prec UMINUS { if(DEBUG_EXP) fprintf(stderr, " !"); $$ = new LogNotExpression($2); lastExp = $$; }
|
|
|
|
| '*' expression %prec DEREF { if(DEBUG_EXP) fprintf(stderr, " U*"); $$ = new ByteDerefExpression($2); lastExp = $$; }
|
|
|
|
| '@' expression %prec DEREF { if(DEBUG_EXP) fprintf(stderr, " U@"); $$ = new WordDerefExpression($2); lastExp = $$; }
|
|
|
|
| '<' expression { if(DEBUG_EXP) fprintf(stderr, " U<"); $$ = new LoByteExpression($2); lastExp = $$; }
|
|
|
|
| '>' expression { if(DEBUG_EXP) fprintf(stderr, " U>"); $$ = new HiByteExpression($2); lastExp = $$; }
|
|
|
|
| '(' expression ')' { if(DEBUG_EXP) fprintf(stderr, " ()"); $$ = $2; lastExp = $$; }
|
|
|
|
| expression '[' expression ']' { if(DEBUG_EXP) fprintf(stderr, " []"); $$ = new ByteDerefOffsetExpression($1, $3); lastExp = $$; }
|
|
|
|
| NUMBER { if(DEBUG_EXP) fprintf(stderr, " %d", $1); $$ = new ConstExpression($1); lastExp = $$; }
|
|
|
|
| EQUATE { if(DEBUG_EXP) fprintf(stderr, " %s", $1); $$ = new EquateExpression($1); lastExp = $$; }
|
|
|
|
| CPU_METHOD { if(DEBUG_EXP) fprintf(stderr, " (CpuMethod)"); $$ = new CpuMethodExpression($1); lastExp = $$; }
|
|
|
|
| TIA_METHOD { if(DEBUG_EXP) fprintf(stderr, " (TiaMethod)"); $$ = new TiaMethodExpression($1); lastExp = $$; }
|
|
|
|
| FUNCTION { if(DEBUG_EXP) fprintf(stderr, " (function)"); $$ = new FunctionExpression($1); lastExp = $$; }
|
|
|
|
| ERR { if(DEBUG_EXP) fprintf(stderr, " ERR"); yyerror("Invalid label or constant"); return 1; }
|
2005-07-01 04:29:18 +00:00
|
|
|
;
|
|
|
|
%%
|