ref: 4457deb19fb16af77ee0f0f8b3ea745b3fe41e1d
parent: e01f61f0d55b37630264e8d74107199752a6e76f
author: Jacob Moody <moody@posixcafe.org>
date: Fri Apr 26 02:55:03 EDT 2024
enough to generate basic c programs
--- a/dat.h
+++ b/dat.h
@@ -78,6 +78,7 @@
Oinc,
Odec,
Orcv,
+ Oind,
};
enum {
@@ -157,6 +158,7 @@
#pragma varargck type "O" Nod*
#pragma varargck type "L" Nlst
#pragma varargck type "M" Nlst
+#pragma varargck type "P" Nlst
extern int lexline;
extern char* lexfile;
--- a/fmt.c
+++ b/fmt.c
@@ -28,7 +28,7 @@
[Orcv] "←"
};
-static char tabs[128];
+static char tabs[128], stars[128];
int
nodfmt(Fmt *f)
@@ -67,6 +67,8 @@
case Nexpr:
if(n->expr.op == Olit || n->expr.op == Ovar)
return fmtprint(f, "%N", n->expr.lhs);
+ else if(n->expr.op == Oind)
+ return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
else
return fmtprint(f, "EXPR(%N %s %N)", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
case Nblk:
@@ -103,7 +105,9 @@
cnodfmt(Fmt *f)
{
Nod *n;
+ char *t;
int nt, e;
+ Typ *ty;
nt = f->prec;
n = va_arg(f->args, Nod*);
@@ -134,6 +138,8 @@
case Nexpr:
if(n->expr.op == Olit || n->expr.op == Ovar)
return fmtprint(f, "%O", n->expr.lhs);
+ else if(n->expr.op == Oind)
+ return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
else
return fmtprint(f, "%O %s %O", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
case Nblk:
@@ -140,11 +146,19 @@
e = nt - 1;
if(e < 0)
e = 0;
- return fmtprint(f, "{\n%.*M\n%.*s}", nt, n->blk.body, e, tabs);
+ return fmtprint(f, "{\n%.*P\n%.*s}", nt, n->blk.body, e, tabs);
case Ndcl:
- return fmtprint(f, "%s %s", n->dcl.type->name, n->dcl.name);
+ e = 0;
+ for(ty = n->dcl.type; ty->t == Tslice; ty = ty->base)
+ e++;
+ return fmtprint(f, "%s %.*s%s", ty->name, e, stars, n->dcl.name);
case Nfunc:
- return fmtprint(f, "void\n%s(%M)\n%.*O", n->func.name, n->func.args, nt+1, n->func.body);
+ t = n->func.type->base->name;
+ if(n->func.args.nv == 0)
+ fmtprint(f, "%s\n%s(void)", t, n->func.name);
+ else
+ fmtprint(f, "%s\n%s(%M)", t, n->func.name, n->func.args);
+ return fmtprint(f, "\n%.*O", nt+1, n->func.body);
case Ncall:
return fmtprint(f, "%s(%M)", n->call.name, n->call.args);
}
@@ -166,13 +180,36 @@
return 0;
}
+int
+cnlstfmtblk(Fmt *f)
+{
+ int i, nt;
+ Nlst n;
+
+ nt = f->prec;
+ n = va_arg(f->args, Nlst);
+ for(i = 0; i < n.nv; i++){
+ fmtprint(f, "%.*O", nt, n.v[i]);
+ switch(n.v[i]->t){
+ case Ncall: case Ndcl: case Nexpr:
+ fmtprint(f, ";");
+ }
+ if(i != n.nv-1)
+ fmtprint(f, "\n");
+ }
+ return 0;
+}
+
void
astfmtinstall(void)
{
memset(tabs, '\t', nelem(tabs)-1);
tabs[nelem(tabs)-1] = '\0';
+ memset(stars, '*', nelem(stars)-1);
+ tabs[nelem(stars)-1] = '\0';
fmtinstall('N', nodfmt);
fmtinstall('L', nlstfmt);
fmtinstall('O', cnodfmt);
fmtinstall('M', cnlstfmt);
+ fmtinstall('P', cnlstfmtblk);
}
--- a/n.y
+++ b/n.y
@@ -35,9 +35,9 @@
}
%token FUNC DEF IF FOR MOD USE OR AND NOTEQ EQ SHIFTL SHIFTR STRUCT ELSE ARROWR ARROWL GTEQ LTEQ INC DEC
-%token TYPE NAME NUM
+%token TYPE NAME NUM STR
-%token <sval> NAME;
+%token <sval> NAME STR
%token <ival> NUM
%type<nod> defarg expr logexpr shifexpr addexpr mulexpr
@@ -84,7 +84,8 @@
unary
: NUM { $$ = mkexpr(Olit, mkintlit($1), nil); }
| NAME { $$ = mkexpr(Ovar, mksym($1), nil); }
-| '"' NAME '"' { $$ = mkstrlit($2); }
+| STR { $$ = mkstrlit($1); }
+| NAME '[' NUM ']' { $$ = mkexpr(Oind, mksym($1), mkintlit($3)); }
| '(' expr ')' { $$ = $2; }
sufexpr
@@ -215,6 +216,27 @@
}
void
+strlex(char *dst, int n)
+{
+ Rune c;
+ char *e;
+
+ for(e = dst + n - UTFmax; dst < e;){
+ c = getch();
+ if((c >= Runeself)
+ || (c != '"' && c != '\n')){
+ dst += runetochar(dst, &c);
+ continue;
+ }
+ ungetc();
+ break;
+ }
+ if(dst > e - UTFmax*2)
+ yyerror("symbol buffer overrun");
+ *dst = '\0';
+}
+
+void
yyerror(char *s)
{
fprint(2, "%d: %s\n", lexline, s);
@@ -284,8 +306,14 @@
if(getch() == '/')
goto Loop;
goto More;
+ case '"':
+ strlex(buf, sizeof buf);
+ if(getch() != '"')
+ yyerror("non terminated string");
+ yylval.sval = strdup(buf);
+ return STR;
}
- if(utfrune("\"';{}[]()*/%:,.", c) != nil)
+ if(utfrune("';{}[]()*/%:,.", c) != nil)
return c;
for(i = 0; i < nelem(spectab); i++){
if(c != spectab[i].c)
@@ -358,10 +386,13 @@
usage();
break;
}ARGEND;
- if(argc > 0)
+ if(argc > 1)
usage();
astfmtinstall();
- bin = Bfdopen(0, OREAD);
+ if(argc == 0)
+ bin = Bfdopen(0, OREAD);
+ else
+ bin = Bopen(argv[0], OREAD);
goteof = 0;
while(!goteof)
yyparse();
@@ -369,6 +400,6 @@
if(ast)
print("%L\n", toplevel);
else
- print("%M\n", toplevel);
+ print("#include <u.h>\n#include <libc.h>\n\n%P\n", toplevel);
exits(nil);
}