You know, when adding a directory to a proejct, it's often beneficial

to "cvs add" it...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@586 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-07-01 04:29:18 +00:00
parent 073ae410ad
commit e91ac28927
9 changed files with 1601 additions and 0 deletions

View File

@ -0,0 +1,17 @@
### Note: this Makefile not used in building the main Stella binary!
# can use "yacc" instead of "bison -y"
all: stella.y
bison -y -d stella.y
calctest: stella.y calctest.c YaccParser.cxx YaccParser.hxx
bison -y -d stella.y
g++ -DPRINT -O2 -c YaccParser.cxx
g++ -O2 -c calctest.c
g++ -O2 -Wall -o calctest calctest.o YaccParser.o
strip calctest
#clean:
# rm -f y.tab.* lex.yy.* *.o calctest

View File

@ -0,0 +1,27 @@
Makefile.yacc - Not part of the regular stella build!
YaccParser.cxx - C++ wrapper for generated parser, includes hand-coded lexer
YaccParser.hxx - Include in user code, declares public "methods" (actually functions)
calctest.c - Not part of stella! Used for testing the lexel/parser.
module.mk - Used for regular Stella build
stella.y - Yacc/Bison source for parser
y.tab.c, y.tab.h - Generated parser. NOT BUILT AUTOMATICALLY!
I've only tested stella.y with GNU bison 1.35 and (once) with Berkeley
Yacc 1.9. Hopefully your favorite version will work, too :)
Even though they're generated, y.tab.c and .h are in CVS. This is so that
people who don't have a local copy of bison or yacc can still compile
Stella.
If you modify stella.y, you MUST run "make -f Makefile.yacc" in this directory.
This will regenerate y.tab.c and y.tab.h. Do this before "cvs commit".
If you're hacking the parser, you can test it without the rest of Stella
by running "make -f Makefile.yacc calctest" in this directory, then running
calctest with an expression as its argument:
./calctest '2+2'
= 4
If you're trying to benchmark the lexer/parser, try adding -DBM to the
g++ command that builds calctest.

View File

@ -0,0 +1,162 @@
//#include "YaccParser.hxx"
namespace YaccParser {
#include <stdio.h>
#include <ctype.h>
int result;
//#include "y.tab.h"
#include "y.tab.c"
int getResult() {
return result;
}
const char *input, *c;
enum {
ST_DEFAULT,
ST_NUMBER,
ST_OPERATOR,
ST_SPACE
};
int state = ST_DEFAULT;
//extern int yylval; // bison provides this
void setInput(const char *in) {
input = c = in;
state = ST_DEFAULT;
}
int parse(const char *in) {
setInput(in);
return yyparse();
}
/* hand-rolled lexer. Hopefully faster than flex... */
#define is_operator(x) ( (x=='+' || x=='-' || x=='*' || \
x=='/' || x=='<' || x=='>' || \
x=='|' || x=='&' || x=='^' || \
x=='!' || x=='~' || x=='(' || \
x==')' || x=='=' ) )
int yylex() {
char o, p;
yylval = 0;
while(*c != '\0') {
//fprintf(stderr, "looking at %c, state %d\n", *c, state);
switch(state) {
case ST_SPACE:
yylval = 0;
if(isspace(*c)) {
c++;
} else if(isdigit(*c)) {
state = ST_NUMBER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
state = ST_DEFAULT;
}
break;
case ST_NUMBER:
while(isdigit(*c)) {
yylval *= 10;
yylval += (*c++ - '0');
//fprintf(stderr, "yylval==%d, *c==%c\n", yylval, *c);
}
state = ST_DEFAULT;
return NUMBER;
/*
if(isdigit(*c)) {
yylval *= 10;
yylval += (*c - '0');
c++;
//fprintf(stderr, "*c==0? %d\n", *c==0);
if(*c == '\0') return NUMBER;
break;
} else {
state = ST_DEFAULT;
return NUMBER;
}
*/
case ST_OPERATOR:
o = *c++;
if(!*c) return o;
if(isspace(*c)) {
state = ST_SPACE;
return o;
} else if(isdigit(*c)) {
state = ST_NUMBER;
return o;
} else {
state = ST_DEFAULT;
p = *c++;
//fprintf(stderr, "o==%c, p==%c\n", o, p);
if(o == '>' && p == '=')
return GTE;
else if(o == '<' && p == '=')
return LTE;
else if(o == '!' && p == '=')
return NE;
else if(o == '=' && p == '=')
return EQ;
else if(o == '|' && p == '|')
return LOG_OR;
else if(o == '&' && p == '&')
return LOG_AND;
else if(o == '<' && p == '<')
return SHL;
else if(o == '>' && p == '>')
return SHR;
else {
c--;
return o;
}
}
break;
case ST_DEFAULT:
default:
yylval = 0;
if(isspace(*c)) {
state = ST_SPACE;
} else if(isdigit(*c)) {
state = ST_NUMBER;
} else if(is_operator(*c)) {
state = ST_OPERATOR;
} else {
yylval = *c++;
return yylval;
}
break;
}
}
//fprintf(stderr, "end of input\n");
return 0; // hit NUL, end of input.
}
#if 0
int main(int argc, char **argv) {
int l;
set_input(argv[1]);
while( (l = yylex()) != 0 )
printf("ret %d, %d\n", l, yylval);
printf("%d\n", yylval);
}
#endif
}

View File

@ -0,0 +1,10 @@
#ifndef PARSER_HXX
#define PARSER_HXX
namespace YaccParser {
int parse(const char *);
int getResult();
};
#endif

View File

@ -0,0 +1,25 @@
#include <stdio.h>
#include <string.h>
#include "YaccParser.hxx"
//extern int YaccParser::yyparse();
//extern void YaccParser::set_input(const char *);
//extern int yyrestart(FILE *);
int main(int argc, char **argv) {
#ifndef BM
YaccParser::parse(argv[1]);
printf("= %d\n", YaccParser::getResult());
#else
char buf[10];
for(int i=0; i<1000000; i++) {
sprintf(buf, "(1<2)&(3+4)");
YaccParser::parse(buf);
}
#endif
}

10
stella/src/yacc/module.mk Normal file
View File

@ -0,0 +1,10 @@
MODULE := src/yacc
MODULE_OBJS := \
src/yacc/YaccParser.o
MODULE_DIRS += \
src/yacc
# Include common rules
include $(srcdir)/common.rules

65
stella/src/yacc/stella.y Normal file
View File

@ -0,0 +1,65 @@
%{
#include <stdio.h>
#define YYERROR_VERBOSE 1
int yylex();
char *yytext;
void yyerror(char *e) {
//fprintf(stderr, "%s at token \"%s\"\n", e, yytext);
fprintf(stderr, "%s\n", e);
}
%}
%token NUMBER
%left '-' '+'
%left '*' '/' '%'
%left LOG_OR
%left LOG_AND
%left '|' '^'
%left '&'
%left SHR SHL
%nonassoc UMINUS '<' '>' GTE LTE NE EQ
%%
statement: expression { result = $1; }
;
expression: expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| expression '*' expression { $$ = $1 * $3; }
| expression '/' expression
{ if($3 == 0)
yyerror("divide by zero");
else
$$ = $1 / $3;
}
| expression '%' expression
{ if($3 == 0)
yyerror("divide by zero");
else
$$ = $1 % $3;
}
| expression '&' expression { $$ = $1 & $3; }
| expression '|' expression { $$ = $1 | $3; }
| expression '^' expression { $$ = $1 ^ $3; }
| expression '>' expression { $$ = $1 > $3; }
| expression '<' expression { $$ = $1 < $3; }
| expression GTE expression { $$ = $1 >= $3; }
| expression LTE expression { $$ = $1 <= $3; }
| expression NE expression { $$ = $1 != $3; }
| expression EQ expression { $$ = $1 == $3; }
| expression SHR expression { $$ = $1 >> $3; }
| expression SHL expression { $$ = $1 << $3; }
| expression LOG_OR expression { $$ = $1 || $3; }
| expression LOG_AND expression { $$ = $1 && $3; }
| '-' expression %prec UMINUS { $$ = -$2; }
| '~' expression %prec UMINUS { $$ = (~$2) & 0xffff; }
| '<' expression %prec UMINUS { $$ = $2 & 0xff; }
| '>' expression %prec UMINUS { $$ = ($2 >> 8) & 0xff; }
| '(' expression ')' { $$ = $2; }
| NUMBER
;
%%

1263
stella/src/yacc/y.tab.c Normal file

File diff suppressed because it is too large Load Diff

22
stella/src/yacc/y.tab.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef BISON_Y_TAB_H
# define BISON_Y_TAB_H
# ifndef YYSTYPE
# define YYSTYPE int
# define YYSTYPE_IS_TRIVIAL 1
# endif
# define NUMBER 257
# define LOG_OR 258
# define LOG_AND 259
# define SHR 260
# define SHL 261
# define UMINUS 262
# define GTE 263
# define LTE 264
# define NE 265
# define EQ 266
extern YYSTYPE yylval;
#endif /* not BISON_Y_TAB_H */