shithub: hammer

Download patch

ref: dd9a8551019ff0bfb4c5af583dc60419d28c4bb1
author: Jacob Moody <moody@posixcafe.org>
date: Thu Nov 16 23:15:12 EST 2023

initial commit, rough idea

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+
+BIN=$home/bin/$objtype
+TARG=nl
+OFILES=\
+	y.tab.$O\
+
+YFILES=\
+	n.y\
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/n.y
@@ -1,0 +1,238 @@
+%{
+
+#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);
+}