summary refs log tree commit diff
path: root/minic/minic.y
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-10-08 23:52:44 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-10-08 23:52:44 -0400
commit5d2609b1674bc1d55872392693bf7281f6a83acc (patch)
tree67a41d535a78f0fd336bae2dbf6357fcc380c7a6 /minic/minic.y
parenta72dfedc1f969ad41d9b5d3aee7f7939e7703dd8 (diff)
downloadroux-5d2609b1674bc1d55872392693bf7281f6a83acc.tar.gz
add clumsy support for string literals
It's currently clumsy because they are given the type 'int *'
instead of 'char *', the reason is that the char base type is
not supported now.  I don't think it would be hard to add
proper support for char, though.
Diffstat (limited to 'minic/minic.y')
-rw-r--r--minic/minic.y47
1 files changed, 44 insertions, 3 deletions
diff --git a/minic/minic.y b/minic/minic.y
index 3465ca5..5222869 100644
--- a/minic/minic.y
+++ b/minic/minic.y
@@ -8,9 +8,9 @@
 enum {
 	NString = 16,
 	NVar = 256,
+	NStr = 256,
 };
 
-
 enum { /* minic types */
 	INT = 0,
 	LNG = 1,
@@ -40,6 +40,7 @@ struct Symb {
 		Con,
 		Tmp,
 		Var,
+		Glo,
 	} t;
 	union {
 		int n;
@@ -62,7 +63,8 @@ int yylex(void), yyerror(char *);
 Symb expr(Node *), lval(Node *);
 
 FILE *of;
-int lbl, tmp;
+int lbl, tmp, str;
+char *slit[NStr];
 struct {
 	char v[NString];
 	unsigned ctyp;
@@ -167,6 +169,9 @@ psymb(Symb s)
 	case Con:
 		fprintf(of, "%d", s.u.n);
 		break;
+	case Glo:
+		fprintf(of, "$%s", s.u.v);
+		break;
 	}
 }
 
@@ -275,6 +280,12 @@ expr(Node *n)
 		sr.ctyp = INT;
 		break;
 
+	case 'S':
+		sr.t = Glo;
+		sprintf(sr.u.v, "str%d", n->u.n);
+		sr.ctyp = IDIR(INT);
+		break;
+
 	case '@':
 		s0 = expr(n->l);
 		if (KIND(s0.ctyp) != PTR)
@@ -480,6 +491,7 @@ mkstmt(int t, void *p1, void *p2, void *p3)
 }
 
 %token <n> NUM
+%token <n> STR
 %token <n> IDENT
 %token PP MM LE GE
 
@@ -502,9 +514,13 @@ mkstmt(int t, void *p1, void *p2, void *p3)
 
 prog: prot '{' dcls stmts '}'
 {
+	int i;
+
 	stmt($4);
 	fprintf(of, "\tret\n");
 	fprintf(of, "}\n\n");
+	for (i = 0; i < str; i++)
+		fprintf(of, "data $str%d = \"%s\"\n", i, slit[i]);
 };
 
 prot: IDENT '(' ')'
@@ -512,7 +528,7 @@ prot: IDENT '(' ')'
 	varclr();
 	lbl = 0;
 	tmp = 0;
-	fprintf(of, "function %s() {\n", $1->u.v);
+	fprintf(of, "function $%s() {\n", $1->u.v);
 	fprintf(of, "@l%d\n", lbl++);
 };
 
@@ -566,6 +582,7 @@ pref: post
     ;
 
 post: NUM
+    | STR
     | IDENT
     | '(' expr ')'      { $$ = $2; }
     | post '[' expr ']' { $$ = mkidx($1, $3); }
@@ -630,6 +647,30 @@ yylex()
 		return IDENT;
 	}
 
+	if (c == '"') {
+		if (str == NStr)
+			die("too many string literals");
+		i = 0;
+		n = 32;
+		p = alloc(n);
+		for (i=0;; i++) {
+			c = getchar();
+			if (c == EOF)
+				die("unclosed string literal");
+			if (c == '"' && (!i || p[i-1]!='\\'))
+				break;
+			if (i >= n) {
+				p = memcpy(alloc(n*2), p, n);
+				n *= 2;
+			}
+			p[i] = c;
+		}
+		slit[str] = p;
+		yylval.n = mknode('S', 0, 0);
+		yylval.n->u.n = str++;
+		return STR;
+	}
+
 	c1 = getchar();
 #define DI(a, b) a + b*256
 	switch (DI(c,c1)) {