shithub: hammer

ref: dd9a8551019ff0bfb4c5af583dc60419d28c4bb1
dir: /n.y/

View raw version
%{

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>

int goteof;
int lineno;
int yyparse(void);
void yyerror(char*);

%}

%union
{
	char *sval;
	long ival;
}

%token FUNC DEF IF FOR STRUCT MOD USE TYPE NAME NUM OR AND NOTEQ SHIFTL SHIFTR

%token	<sval>	NAME TYPE;
%token	<ival>	NUM

%%

prog
:	prog top
|	top

sem
:	';'

top
:	FUNC NAME '(' args ')' '-' '>' return '{' stmts '}'
|	MOD NAME sem
|	USE NAME sem

return
:	TYPE
|

unary
:	NUM
|	NAME	

mulexpr
:	mulexpr '*' unary
|	mulexpr '/' unary
|	mulexpr '%' unary
|	unary


addexpr
:	addexpr '+' mulexpr
|	addexpr '-' mulexpr
|	mulexpr

compexpr
:	compexpr '>' addexpr
|	compexpr '<' addexpr
|	compexpr NOTEQ addexpr
|	addexpr


logexpr
:	logexpr OR compexpr
|	logexpr AND compexpr
|	compexpr

expr
:	
|	expr '=' logexpr
|	logexpr

stmts
:
|	stmts stmt

decl
:	NAME ':' expr

stmt
:	expr sem
|	'{' stmts '}'
|	decl sem

args
:	NAME

%%

Biobuf *bin;

int
getch(void)
{
	int c;

	c = Bgetc(bin);
	if(c == Beof){
		goteof = 1;
		return -1;
	}
	if(c == '\n')
		lineno++;
	return c;
}

void
ungetc(void)
{
	Bungetc(bin);
}

void
wordlex(char *dst, int n)
{
	int c;

	while(--n > 0){
		c = getch();
		if((c >= Runeself)
		|| isalnum(c)){
			*dst++ = c;
			continue;
		}
		ungetc();
		break;
	}
	if(n <= 0)
		yyerror("symbol buffer overrun");
	*dst = '\0';
}

void
yyerror(char *s)
{
	fprint(2, "%d: %s\n", lineno, s);
	exits(s);
}

int
yylex2(void)
{
	static char buf[200];
	int c;
	int i;

Loop:
	c = getch();
	switch(c){
	case -1:
		return -1;
	case ' ':
	case '\t':
	case '\n':
		goto Loop;
	case '/':
		if(getch() != '*'){
			ungetc();
			goto Loop;
		}
More:
		while((c = getch()) > 0)
			if(c == '*')
				break;
		if(c != '*')
			goto Loop;
		if(getch() == '/')
			goto Loop;
		goto More;
	}

	switch(c){
	case ';': case '=':
	case '{': case '}':
	case '[': case ']':
	case '(': case ')':
	case '+': case '-':
	case '*': case '/':
	case '%':
	case '>': case '<':
		return c;
	}
	ungetc();
	wordlex(buf, sizeof buf);

	if(strcmp(buf, "fn") == 0)
		return FUNC;
	if(strcmp(buf, "||") == 0)
		return OR;
	if(strcmp(buf, "&&") == 0)
		return AND;

	if(isdigit(buf[0])){
		yylval.ival = atoi(buf);
		return NUM;
	}

	yylval.sval = strdup(buf);
	return NAME;
}

int
yylex(void)
{
	int c;

	c = yylex2();
	return c;
}

void
usage(void)
{
	fprint(2, "usage: %s\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	ARGBEGIN{
	default:
		usage();
		break;
	}ARGEND;
	if(argc > 0)
		usage();
	bin = Bfdopen(0, OREAD);
	goteof = 0;
	while(!goteof)
		yyparse();
	Bterm(bin);
	exits(nil);
}