├── README.md ├── chap1 ├── main.c ├── makefile ├── prog1.c ├── prog1.h ├── slp.c ├── slp.h ├── util.c └── util.h ├── chap10 ├── flowgraph.h ├── graph.c └── graph.h ├── chap11 ├── color.h └── regalloc.h ├── chap12 └── runtime.c ├── chap2 ├── driver.c ├── errormsg.c ├── errormsg.h ├── makefile ├── tiger.lex ├── tokens.h ├── util.c └── util.h ├── chap3 ├── errormsg.c ├── errormsg.h ├── lex.yy.c ├── makefile ├── parsetest.c ├── tiger.grm ├── util.c ├── util.h └── y.output ├── chap4 ├── absyn.c ├── absyn.h ├── lex.yy.c ├── makefile ├── parse.c ├── parse.h ├── prabsyn.c ├── prabsyn.h ├── symbol.c ├── symbol.h ├── table.c ├── table.h └── tiger.grm ├── chap5 ├── types.c └── types.h ├── chap6 ├── temp.c └── temp.h ├── chap7 ├── printtree.c ├── printtree.h ├── tree.c └── tree.h ├── chap8 ├── canon.c └── canon.h ├── chap9 ├── assem.c ├── assem.h ├── canon.c ├── canon.h └── main.c └── testcases ├── merge.tig ├── queens.tig ├── test1.tig ├── test10.tig ├── test11.tig ├── test12.tig ├── test13.tig ├── test14.tig ├── test15.tig ├── test16.tig ├── test17.tig ├── test18.tig ├── test19.tig ├── test2.tig ├── test20.tig ├── test21.tig ├── test22.tig ├── test23.tig ├── test24.tig ├── test25.tig ├── test26.tig ├── test27.tig ├── test28.tig ├── test29.tig ├── test3.tig ├── test30.tig ├── test31.tig ├── test32.tig ├── test33.tig ├── test34.tig ├── test35.tig ├── test36.tig ├── test37.tig ├── test38.tig ├── test39.tig ├── test4.tig ├── test40.tig ├── test41.tig ├── test42.tig ├── test43.tig ├── test44.tig ├── test45.tig ├── test46.tig ├── test47.tig ├── test48.tig ├── test49.tig ├── test5.tig ├── test6.tig ├── test7.tig ├── test8.tig └── test9.tig /README.md: -------------------------------------------------------------------------------- 1 | # modern-compiler 2 | 现代编译原理(虎书) 3 | 4 | ## 课程目录 5 | ``` 6 | Part I Fundamentals of Compilation 7 | 1 Introduction 8 | 1.1 Modules and interfaces 9 | 1.2 Tools and software 10 | 1.3 Data structures of tree languages 11 | 12 | 2 Lexical Analysis 13 | 2.1 Lexical tokens 14 | 2.2 Regular expressions 15 | 2.3 Finite automata 16 | 2.4 Nondeterministic finite automata 17 | 2.5 Lex: a lexical analyzer generator 18 | 19 | 3 Parsing 20 | 3.1 Context-free grammars 21 | 3.2 Predictive parsing 22 | 3.3 LR parsing 23 | 3.4 Using parser generators 24 | 3.5 Error recovery 25 | 26 | 4 Abstract Syntax 27 | 5 Semantic Analysis 28 | 6 Activation Records 29 | 7 Translation to intermediate Code 30 | 8 Basic Blocks and Traces 31 | 9 Instrction Selection 32 | 10 Liveness Analysis 33 | 11 Register Allocation 34 | 12 Putting it all Together 35 | 3.1 Context-free grammars 36 | 3.2 Predictive parsing 37 | 38 | Part II Advanced Topics 39 | 13 Garbage Collection 40 | 14 Object-Oriented Languages 41 | 15 Functional Programming Languages 42 | 16 Polymorphic Types 43 | 17 Dataflow Analysis 44 | 18 Loop Optimizations 45 | 19 Static Single-Assignment Form 46 | 20 Pipelining and Scheduling 47 | 21 The Memory Hierarchy 48 | 49 | Appendix: Tiger Language Reference Manual 50 | ``` 51 | -------------------------------------------------------------------------------- /chap1/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /chap1/makefile: -------------------------------------------------------------------------------- 1 | a.out: main.o prog1.o slp.o util.o 2 | cc -g main.o prog1.o slp.o util.o 3 | 4 | main.o: main.c slp.h util.h 5 | cc -g -c main.c 6 | 7 | prog1.o: prog1.c slp.h util.h 8 | cc -g -c prog1.c 9 | 10 | slp.o: slp.c slp.h util.h 11 | cc -g -c slp.c 12 | 13 | util.o: util.c util.h 14 | cc -g -c util.c 15 | 16 | clean: 17 | rm -f a.out util.o prog1.o slp.o main.o 18 | -------------------------------------------------------------------------------- /chap1/prog1.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "slp.h" 3 | 4 | A_stm prog(void) { 5 | 6 | return 7 | A_CompoundStm(A_AssignStm("a", 8 | A_OpExp(A_NumExp(5), A_plus, A_NumExp(3))), 9 | A_CompoundStm(A_AssignStm("b", 10 | A_EseqExp(A_PrintStm(A_PairExpList(A_IdExp("a"), 11 | A_LastExpList(A_OpExp(A_IdExp("a"), A_minus, 12 | A_NumExp(1))))), 13 | A_OpExp(A_NumExp(10), A_times, A_IdExp("a")))), 14 | A_PrintStm(A_LastExpList(A_IdExp("b"))))); 15 | } 16 | -------------------------------------------------------------------------------- /chap1/prog1.h: -------------------------------------------------------------------------------- 1 | A_stm prog(void); 2 | -------------------------------------------------------------------------------- /chap1/slp.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "slp.h" 3 | 4 | A_stm A_CompoundStm(A_stm stm1, A_stm stm2) { 5 | A_stm s = checked_malloc(sizeof *s); 6 | s->kind=A_compoundStm; s->u.compound.stm1=stm1; s->u.compound.stm2=stm2; 7 | return s; 8 | } 9 | 10 | 11 | A_stm A_AssignStm(string id, A_exp exp) { 12 | A_stm s = checked_malloc(sizeof *s); 13 | s->kind=A_assignStm; s->u.assign.id=id; s->u.assign.exp=exp; 14 | return s; 15 | } 16 | 17 | A_stm A_PrintStm(A_expList exps) { 18 | A_stm s = checked_malloc(sizeof *s); 19 | s->kind=A_printStm; s->u.print.exps=exps; 20 | return s; 21 | } 22 | 23 | A_exp A_IdExp(string id) { 24 | A_exp e = checked_malloc(sizeof *e); 25 | e->kind=A_idExp; e->u.id=id; 26 | return e; 27 | } 28 | 29 | A_exp A_NumExp(int num) { 30 | A_exp e = checked_malloc(sizeof *e); 31 | e->kind=A_numExp; e->u.num=num; 32 | return e; 33 | } 34 | 35 | A_exp A_OpExp(A_exp left, A_binop oper, A_exp right) { 36 | A_exp e = checked_malloc(sizeof *e); 37 | e->kind=A_opExp; e->u.op.left=left; e->u.op.oper=oper; e->u.op.right=right; 38 | return e; 39 | } 40 | 41 | A_exp A_EseqExp(A_stm stm, A_exp exp) { 42 | A_exp e = checked_malloc(sizeof *e); 43 | e->kind=A_eseqExp; e->u.eseq.stm=stm; e->u.eseq.exp=exp; 44 | return e; 45 | } 46 | 47 | A_expList A_PairExpList(A_exp head, A_expList tail) { 48 | A_expList e = checked_malloc(sizeof *e); 49 | e->kind=A_pairExpList; e->u.pair.head=head; e->u.pair.tail=tail; 50 | return e; 51 | } 52 | 53 | A_expList A_LastExpList(A_exp last) { 54 | A_expList e = checked_malloc(sizeof *e); 55 | e->kind=A_lastExpList; e->u.last=last; 56 | return e; 57 | } 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /chap1/slp.h: -------------------------------------------------------------------------------- 1 | typedef struct A_stm_ *A_stm; 2 | typedef struct A_exp_ *A_exp; 3 | typedef struct A_expList_ *A_expList; 4 | typedef enum {A_plus,A_minus,A_times,A_div} A_binop; 5 | 6 | struct A_stm_ {enum {A_compoundStm, A_assignStm, A_printStm} kind; 7 | union {struct {A_stm stm1, stm2;} compound; 8 | struct {string id; A_exp exp;} assign; 9 | struct {A_expList exps;} print; 10 | } u; 11 | }; 12 | A_stm A_CompoundStm(A_stm stm1, A_stm stm2); 13 | A_stm A_AssignStm(string id, A_exp exp); 14 | A_stm A_PrintStm(A_expList exps); 15 | 16 | struct A_exp_ {enum {A_idExp, A_numExp, A_opExp, A_eseqExp} kind; 17 | union {string id; 18 | int num; 19 | struct {A_exp left; A_binop oper; A_exp right;} op; 20 | struct {A_stm stm; A_exp exp;} eseq; 21 | } u; 22 | }; 23 | A_exp A_IdExp(string id); 24 | A_exp A_NumExp(int num); 25 | A_exp A_OpExp(A_exp left, A_binop oper, A_exp right); 26 | A_exp A_EseqExp(A_stm stm, A_exp exp); 27 | 28 | struct A_expList_ {enum {A_pairExpList, A_lastExpList} kind; 29 | union {struct {A_exp head; A_expList tail;} pair; 30 | A_exp last; 31 | } u; 32 | }; 33 | 34 | A_expList A_PairExpList(A_exp head, A_expList tail); 35 | A_expList A_LastExpList(A_exp last); 36 | 37 | -------------------------------------------------------------------------------- /chap1/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c - commonly used utility functions. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "util.h" 9 | void *checked_malloc(int len) 10 | {void *p = malloc(len); 11 | if (!p) { 12 | fprintf(stderr,"\nRan out of memory!\n"); 13 | exit(1); 14 | } 15 | return p; 16 | } 17 | 18 | string String(char *s) 19 | {string p = checked_malloc(strlen(s)+1); 20 | strcpy(p,s); 21 | return p; 22 | } 23 | 24 | U_boolList U_BoolList(bool head, U_boolList tail) 25 | { U_boolList list = checked_malloc(sizeof(*list)); 26 | list->head = head; 27 | list->tail = tail; 28 | return list; 29 | } 30 | -------------------------------------------------------------------------------- /chap1/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef char *string; 4 | typedef char bool; 5 | 6 | #define TRUE 1 7 | #define FALSE 0 8 | 9 | void *checked_malloc(int); 10 | string String(char *); 11 | 12 | typedef struct U_boolList_ *U_boolList; 13 | struct U_boolList_ {bool head; U_boolList tail;}; 14 | U_boolList U_BoolList(bool head, U_boolList tail); 15 | 16 | -------------------------------------------------------------------------------- /chap10/flowgraph.h: -------------------------------------------------------------------------------- 1 | /* 2 | * flowgraph.h - Function prototypes to represent control flow graphs. 3 | */ 4 | 5 | Temp_tempList FG_def(G_node n); 6 | Temp_tempList FG_use(G_node n); 7 | bool FG_isMove(G_node n); 8 | G_graph FG_AssemFlowGraph(AS_instrList il); 9 | -------------------------------------------------------------------------------- /chap10/graph.c: -------------------------------------------------------------------------------- 1 | /* 2 | * graph.c - Functions to manipulate and create control flow and 3 | * interference graphs. 4 | */ 5 | 6 | #include 7 | #include "util.h" 8 | #include "symbol.h" 9 | #include "temp.h" 10 | #include "tree.h" 11 | #include "absyn.h" 12 | #include "assem.h" 13 | #include "frame.h" 14 | #include "graph.h" 15 | #include "errormsg.h" 16 | #include "table.h" 17 | 18 | struct G_graph_ {int nodecount; 19 | G_nodeList mynodes, mylast; 20 | }; 21 | 22 | struct G_node_ { 23 | G_graph mygraph; 24 | int mykey; 25 | G_nodeList succs; 26 | G_nodeList preds; 27 | void *info; 28 | }; 29 | 30 | G_graph G_Graph(void) 31 | {G_graph g = (G_graph) checked_malloc(sizeof *g); 32 | g->nodecount = 0; 33 | g->mynodes = NULL; 34 | g->mylast = NULL; 35 | return g; 36 | } 37 | 38 | G_nodeList G_NodeList(G_node head, G_nodeList tail) 39 | {G_nodeList n = (G_nodeList) checked_malloc(sizeof *n); 40 | n->head=head; 41 | n->tail=tail; 42 | return n; 43 | } 44 | 45 | /* generic creation of G_node */ 46 | G_node G_Node(G_graph g, void *info) 47 | {G_node n = (G_node)checked_malloc(sizeof *n); 48 | G_nodeList p = G_NodeList(n, NULL); 49 | assert(g); 50 | n->mygraph=g; 51 | n->mykey=g->nodecount++; 52 | 53 | if (g->mylast==NULL) 54 | g->mynodes=g->mylast=p; 55 | else g->mylast = g->mylast->tail = p; 56 | 57 | n->succs=NULL; 58 | n->preds=NULL; 59 | n->info=info; 60 | return n; 61 | } 62 | 63 | G_nodeList G_nodes(G_graph g) 64 | { 65 | assert(g); 66 | return g->mynodes; 67 | } 68 | 69 | /* return true if a is in l list */ 70 | bool G_inNodeList(G_node a, G_nodeList l) { 71 | G_nodeList p; 72 | for(p=l; p!=NULL; p=p->tail) 73 | if (p->head==a) return TRUE; 74 | return FALSE; 75 | } 76 | 77 | void G_addEdge(G_node from, G_node to) { 78 | assert(from); assert(to); 79 | assert(from->mygraph == to->mygraph); 80 | if (G_goesTo(from, to)) return; 81 | to->preds=G_NodeList(from, to->preds); 82 | from->succs=G_NodeList(to, from->succs); 83 | } 84 | 85 | static G_nodeList delete(G_node a, G_nodeList l) { 86 | assert(a && l); 87 | if (a==l->head) return l->tail; 88 | else return G_NodeList(l->head, delete(a, l->tail)); 89 | } 90 | 91 | void G_rmEdge(G_node from, G_node to) { 92 | assert(from && to); 93 | to->preds=delete(from,to->preds); 94 | from->succs=delete(to,from->succs); 95 | } 96 | 97 | /** 98 | * Print a human-readable dump for debugging. 99 | */ 100 | void G_show(FILE *out, G_nodeList p, void showInfo(void *)) { 101 | for (; p!=NULL; p=p->tail) { 102 | G_node n = p->head; 103 | G_nodeList q; 104 | assert(n); 105 | if (showInfo) 106 | showInfo(n->info); 107 | fprintf(out, " (%d): ", n->mykey); 108 | for(q=G_succ(n); q!=NULL; q=q->tail) 109 | fprintf(out, "%d ", q->head->mykey); 110 | fprintf(out, "\n"); 111 | } 112 | } 113 | 114 | G_nodeList G_succ(G_node n) { assert(n); return n->succs; } 115 | 116 | G_nodeList G_pred(G_node n) { assert(n); return n->preds; } 117 | 118 | bool G_goesTo(G_node from, G_node n) { 119 | return G_inNodeList(n, G_succ(from)); 120 | } 121 | 122 | /* return length of predecessor list for node n */ 123 | static int inDegree(G_node n) 124 | { int deg = 0; 125 | G_nodeList p; 126 | for(p=G_pred(n); p!=NULL; p=p->tail) deg++; 127 | return deg; 128 | } 129 | 130 | /* return length of successor list for node n */ 131 | static int outDegree(G_node n) 132 | { int deg = 0; 133 | G_nodeList p; 134 | for(p=G_succ(n); p!=NULL; p=p->tail) deg++; 135 | return deg; 136 | } 137 | 138 | int G_degree(G_node n) {return inDegree(n)+outDegree(n);} 139 | 140 | /* put list b at the back of list a and return the concatenated list */ 141 | static G_nodeList cat(G_nodeList a, G_nodeList b) { 142 | if (a==NULL) return b; 143 | else return G_NodeList(a->head, cat(a->tail, b)); 144 | } 145 | 146 | /* create the adjacency list for node n by combining the successor and 147 | * predecessor lists of node n */ 148 | G_nodeList G_adj(G_node n) {return cat(G_succ(n), G_pred(n));} 149 | 150 | void *G_nodeInfo(G_node n) {return n->info;} 151 | 152 | 153 | 154 | /* G_node table functions */ 155 | 156 | G_table G_empty(void) { 157 | return TAB_empty(); 158 | } 159 | 160 | void G_enter(G_table t, G_node node, void *value) 161 | { 162 | TAB_enter(t, node, value); 163 | } 164 | 165 | void *G_look(G_table t, G_node node) 166 | { 167 | return TAB_look(t, node); 168 | } 169 | 170 | 171 | -------------------------------------------------------------------------------- /chap10/graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | * graph.h - Abstract Data Type (ADT) for directed graphs 3 | */ 4 | 5 | typedef struct G_graph_ *G_graph; /* The "graph" type */ 6 | typedef struct G_node_ *G_node; /* The "node" type */ 7 | 8 | typedef struct G_nodeList_ *G_nodeList; 9 | struct G_nodeList_ { G_node head; G_nodeList tail;}; 10 | 11 | /* Make a new graph */ 12 | G_graph G_Graph(void); 13 | /* Make a new node in graph "g", with associated "info" */ 14 | G_node G_Node(G_graph g, void *info); 15 | 16 | /* Make a NodeList cell */ 17 | G_nodeList G_NodeList(G_node head, G_nodeList tail); 18 | 19 | /* Get the list of nodes belonging to "g" */ 20 | G_nodeList G_nodes(G_graph g); 21 | 22 | /* Tell if "a" is in the list "l" */ 23 | bool G_inNodeList(G_node a, G_nodeList l); 24 | 25 | /* Make a new edge joining nodes "from" and "to", which must belong 26 | to the same graph */ 27 | void G_addEdge(G_node from, G_node to); 28 | 29 | /* Delete the edge joining "from" and "to" */ 30 | void G_rmEdge(G_node from, G_node to); 31 | 32 | /* Show all the nodes and edges in the graph, using the function "showInfo" 33 | to print the name of each node */ 34 | void G_show(FILE *out, G_nodeList p, void showInfo(void *)); 35 | 36 | /* Get all the successors of node "n" */ 37 | G_nodeList G_succ(G_node n); 38 | 39 | /* Get all the predecessors of node "n" */ 40 | G_nodeList G_pred(G_node n); 41 | 42 | /* Tell if there is an edge from "from" to "to" */ 43 | bool G_goesTo(G_node from, G_node n); 44 | 45 | /* Tell how many edges lead to or from "n" */ 46 | int G_degree(G_node n); 47 | 48 | /* Get all the successors and predecessors of "n" */ 49 | G_nodeList G_adj(G_node n); 50 | 51 | /* Get the "info" associated with node "n" */ 52 | void *G_nodeInfo(G_node n); 53 | 54 | /* The type of "tables" mapping graph-nodes to information */ 55 | typedef struct TAB_table_ *G_table; 56 | 57 | /* Make a new table */ 58 | G_table G_empty(void); 59 | 60 | /* Enter the mapping "node"->"value" to the table "t" */ 61 | void G_enter(G_table t, G_node node, void *value); 62 | 63 | /* Tell what "node" maps to in table "t" */ 64 | void *G_look(G_table t, G_node node); 65 | -------------------------------------------------------------------------------- /chap11/color.h: -------------------------------------------------------------------------------- 1 | /* 2 | * color.h - Data structures and function prototypes for coloring algorithm 3 | * to determine register allocation. 4 | */ 5 | 6 | struct COL_result {Temp_map coloring; Temp_tempList spills;}; 7 | struct COL_result COL_color(G_graph ig, Temp_map initial, Temp_tempList regs); 8 | 9 | 10 | -------------------------------------------------------------------------------- /chap11/regalloc.h: -------------------------------------------------------------------------------- 1 | /* function prototype from regalloc.c */ 2 | struct RA_result {Temp_map coloring; AS_instrList il;}; 3 | struct RA_result RA_regAlloc(F_frame f, AS_instrList il); 4 | -------------------------------------------------------------------------------- /chap12/runtime.c: -------------------------------------------------------------------------------- 1 | #undef __STDC__ 2 | #include 3 | 4 | 5 | int *initArray(int size, int init) 6 | {int i; 7 | int *a = (int *)malloc(size*sizeof(int)); 8 | for(i=0;ilength!=t->length) return 0; 26 | for(i=0;ilength;i++) if (s->chars[i]!=t->chars[i]) return 0; 27 | return 1; 28 | } 29 | 30 | void print(struct string *s) 31 | {int i; unsigned char *p=s->chars; 32 | for(i=0;ilength;i++,p++) putchar(*p); 33 | } 34 | 35 | void flush() 36 | { 37 | fflush(stdout); 38 | } 39 | 40 | struct string consts[256]; 41 | struct string empty={0,""}; 42 | 43 | int main() 44 | {int i; 45 | for(i=0;i<256;i++) 46 | {consts[i].length=1; 47 | consts[i].chars[0]=i; 48 | } 49 | return tigermain(0 /* static link */); 50 | } 51 | 52 | int ord(struct string *s) 53 | { 54 | if (s->length==0) return -1; 55 | else return s->chars[0]; 56 | } 57 | 58 | struct string *chr(int i) 59 | { 60 | if (i<0 || i>=256) 61 | {printf("chr(%d) out of range\n",i); exit(1);} 62 | return consts+i; 63 | } 64 | 65 | int size(struct string *s) 66 | { 67 | return s->length; 68 | } 69 | 70 | struct string *substring(struct string *s, int first, int n) 71 | { 72 | if (first<0 || first+n>s->length) 73 | {printf("substring([%d],%d,%d) out of range\n",s->length,first,n); 74 | exit(1);} 75 | if (n==1) return consts+s->chars[first]; 76 | {struct string *t = (struct string *)malloc(sizeof(int)+n); 77 | int i; 78 | t->length=n; 79 | for(i=0;ichars[i]=s->chars[first+i]; 80 | return t; 81 | } 82 | } 83 | 84 | struct string *concat(struct string *a, struct string *b) 85 | { 86 | if (a->length==0) return b; 87 | else if (b->length==0) return a; 88 | else {int i, n=a->length+b->length; 89 | struct string *t = (struct string *)malloc(sizeof(int)+n); 90 | t->length=n; 91 | for (i=0;ilength;i++) 92 | t->chars[i]=a->chars[i]; 93 | for(i=0;ilength;i++) 94 | t->chars[i+a->length]=b->chars[i]; 95 | return t; 96 | } 97 | } 98 | 99 | int not(int i) 100 | { return !i; 101 | } 102 | 103 | #undef getchar 104 | 105 | struct string *getchar() 106 | {int i=getc(stdin); 107 | if (i==EOF) return ∅ 108 | else return consts+i; 109 | } 110 | -------------------------------------------------------------------------------- /chap2/driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.h" 3 | #include "errormsg.h" 4 | #include "tokens.h" 5 | 6 | YYSTYPE yylval; 7 | 8 | int yylex(void); /* prototype for the lexing function */ 9 | 10 | 11 | 12 | string toknames[] = { 13 | "ID", "STRING", "INT", "COMMA", "COLON", "SEMICOLON", "LPAREN", 14 | "RPAREN", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "DOT", "PLUS", 15 | "MINUS", "TIMES", "DIVIDE", "EQ", "NEQ", "LT", "LE", "GT", "GE", 16 | "AND", "OR", "ASSIGN", "ARRAY", "IF", "THEN", "ELSE", "WHILE", "FOR", 17 | "TO", "DO", "LET", "IN", "END", "OF", "BREAK", "NIL", "FUNCTION", 18 | "VAR", "TYPE" 19 | }; 20 | 21 | 22 | string tokname(tok) { 23 | return tok<257 || tok>299 ? "BAD_TOKEN" : toknames[tok-257]; 24 | } 25 | 26 | int main(int argc, char **argv) { 27 | string fname; int tok; 28 | if (argc!=2) {fprintf(stderr,"usage: a.out filename\n"); exit(1);} 29 | fname=argv[1]; 30 | EM_reset(fname); 31 | for(;;) { 32 | tok=yylex(); 33 | if (tok==0) break; 34 | switch(tok) { 35 | case ID: case STRING: 36 | printf("%10s %4d %s\n",tokname(tok),EM_tokPos,yylval.sval); 37 | break; 38 | case INT: 39 | printf("%10s %4d %d\n",tokname(tok),EM_tokPos,yylval.ival); 40 | break; 41 | default: 42 | printf("%10s %4d\n",tokname(tok),EM_tokPos); 43 | } 44 | } 45 | return 0; 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /chap2/errormsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * errormsg.c - functions used in all phases of the compiler to give 3 | * error messages about the Tiger program. 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "util.h" 11 | #include "errormsg.h" 12 | 13 | 14 | bool anyErrors= FALSE; 15 | 16 | static string fileName = ""; 17 | 18 | static int lineNum = 1; 19 | 20 | int EM_tokPos=0; 21 | 22 | extern FILE *yyin; 23 | 24 | typedef struct intList {int i; struct intList *rest;} *IntList; 25 | 26 | static IntList intList(int i, IntList rest) 27 | {IntList l= checked_malloc(sizeof *l); 28 | l->i=i; l->rest=rest; 29 | return l; 30 | } 31 | 32 | static IntList linePos=NULL; 33 | 34 | void EM_newline(void) 35 | {lineNum++; 36 | linePos = intList(EM_tokPos, linePos); 37 | } 38 | 39 | void EM_error(int pos, char *message,...) 40 | {va_list ap; 41 | IntList lines = linePos; 42 | int num=lineNum; 43 | 44 | 45 | anyErrors=TRUE; 46 | while (lines && lines->i >= pos) 47 | {lines=lines->rest; num--;} 48 | 49 | if (fileName) fprintf(stderr,"%s:",fileName); 50 | if (lines) fprintf(stderr,"%d.%d: ", num, pos-lines->i); 51 | va_start(ap,message); 52 | vfprintf(stderr, message, ap); 53 | va_end(ap); 54 | fprintf(stderr,"\n"); 55 | 56 | } 57 | 58 | void EM_reset(string fname) 59 | { 60 | anyErrors=FALSE; fileName=fname; lineNum=1; 61 | linePos=intList(0,NULL); 62 | yyin = fopen(fname,"r"); 63 | if (!yyin) {EM_error(0,"cannot open"); exit(1);} 64 | } 65 | 66 | -------------------------------------------------------------------------------- /chap2/errormsg.h: -------------------------------------------------------------------------------- 1 | extern bool EM_anyErrors; 2 | 3 | void EM_newline(void); 4 | 5 | extern int EM_tokPos; 6 | 7 | void EM_error(int, string,...); 8 | void EM_impossible(string,...); 9 | void EM_reset(string filename); 10 | -------------------------------------------------------------------------------- /chap2/makefile: -------------------------------------------------------------------------------- 1 | lextest: driver.o lex.yy.o errormsg.o util.o 2 | cc -g -o lextest driver.o lex.yy.o errormsg.o util.o 3 | 4 | driver.o: driver.c tokens.h errormsg.h util.h 5 | cc -g -c driver.c 6 | 7 | errormsg.o: errormsg.c errormsg.h util.h 8 | cc -g -c errormsg.c 9 | 10 | lex.yy.o: lex.yy.c tokens.h errormsg.h util.h 11 | cc -g -c lex.yy.c 12 | 13 | lex.yy.c: tiger.lex 14 | lex tiger.lex 15 | 16 | util.o: util.c util.h 17 | cc -g -c util.c 18 | 19 | clean: 20 | rm -f a.out util.o driver.o lex.yy.o lex.yy.c errormsg.o 21 | -------------------------------------------------------------------------------- /chap2/tiger.lex: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "util.h" 4 | #include "tokens.h" 5 | #include "errormsg.h" 6 | 7 | int charPos=1; 8 | 9 | int yywrap(void) 10 | { 11 | charPos=1; 12 | return 1; 13 | } 14 | 15 | 16 | void adjust(void) 17 | { 18 | EM_tokPos=charPos; 19 | charPos+=yyleng; 20 | } 21 | 22 | %} 23 | 24 | %% 25 | " " {adjust(); continue;} 26 | \n {adjust(); EM_newline(); continue;} 27 | "," {adjust(); return COMMA;} 28 | for {adjust(); return FOR;} 29 | [0-9]+ {adjust(); yylval.ival=atoi(yytext); return INT;} 30 | . {adjust(); EM_error(EM_tokPos,"illegal token");} 31 | 32 | 33 | -------------------------------------------------------------------------------- /chap2/tokens.h: -------------------------------------------------------------------------------- 1 | typedef union { 2 | int pos; 3 | int ival; 4 | string sval; 5 | } YYSTYPE; 6 | extern YYSTYPE yylval; 7 | 8 | # define ID 257 9 | # define STRING 258 10 | # define INT 259 11 | # define COMMA 260 12 | # define COLON 261 13 | # define SEMICOLON 262 14 | # define LPAREN 263 15 | # define RPAREN 264 16 | # define LBRACK 265 17 | # define RBRACK 266 18 | # define LBRACE 267 19 | # define RBRACE 268 20 | # define DOT 269 21 | # define PLUS 270 22 | # define MINUS 271 23 | # define TIMES 272 24 | # define DIVIDE 273 25 | # define EQ 274 26 | # define NEQ 275 27 | # define LT 276 28 | # define LE 277 29 | # define GT 278 30 | # define GE 279 31 | # define AND 280 32 | # define OR 281 33 | # define ASSIGN 282 34 | # define ARRAY 283 35 | # define IF 284 36 | # define THEN 285 37 | # define ELSE 286 38 | # define WHILE 287 39 | # define FOR 288 40 | # define TO 289 41 | # define DO 290 42 | # define LET 291 43 | # define IN 292 44 | # define END 293 45 | # define OF 294 46 | # define BREAK 295 47 | # define NIL 296 48 | # define FUNCTION 297 49 | # define VAR 298 50 | # define TYPE 299 51 | 52 | -------------------------------------------------------------------------------- /chap2/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c - commonly used utility functions. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "util.h" 9 | void *checked_malloc(int len) 10 | {void *p = malloc(len); 11 | if (!p) { 12 | fprintf(stderr,"\nRan out of memory!\n"); 13 | exit(1); 14 | } 15 | return p; 16 | } 17 | 18 | string String(char *s) 19 | {string p = checked_malloc(strlen(s)+1); 20 | strcpy(p,s); 21 | return p; 22 | } 23 | 24 | U_boolList U_BoolList(bool head, U_boolList tail) 25 | { U_boolList list = checked_malloc(sizeof(*list)); 26 | list->head = head; 27 | list->tail = tail; 28 | return list; 29 | } 30 | -------------------------------------------------------------------------------- /chap2/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef char *string; 4 | typedef char bool; 5 | 6 | #define TRUE 1 7 | #define FALSE 0 8 | 9 | void *checked_malloc(int); 10 | string String(char *); 11 | 12 | typedef struct U_boolList_ *U_boolList; 13 | struct U_boolList_ {bool head; U_boolList tail;}; 14 | U_boolList U_BoolList(bool head, U_boolList tail); 15 | 16 | -------------------------------------------------------------------------------- /chap3/errormsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * errormsg.c - functions used in all phases of the compiler to give 3 | * error messages about the Tiger program. 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "util.h" 11 | #include "errormsg.h" 12 | 13 | 14 | bool anyErrors= FALSE; 15 | 16 | static string fileName = ""; 17 | 18 | static int lineNum = 1; 19 | 20 | int EM_tokPos=0; 21 | 22 | extern FILE *yyin; 23 | 24 | typedef struct intList {int i; struct intList *rest;} *IntList; 25 | 26 | static IntList intList(int i, IntList rest) 27 | {IntList l= checked_malloc(sizeof *l); 28 | l->i=i; l->rest=rest; 29 | return l; 30 | } 31 | 32 | static IntList linePos=NULL; 33 | 34 | void EM_newline(void) 35 | {lineNum++; 36 | linePos = intList(EM_tokPos, linePos); 37 | } 38 | 39 | void EM_error(int pos, char *message,...) 40 | {va_list ap; 41 | IntList lines = linePos; 42 | int num=lineNum; 43 | 44 | 45 | anyErrors=TRUE; 46 | while (lines && lines->i >= pos) 47 | {lines=lines->rest; num--;} 48 | 49 | if (fileName) fprintf(stderr,"%s:",fileName); 50 | if (lines) fprintf(stderr,"%d.%d: ", num, pos-lines->i); 51 | va_start(ap,message); 52 | vfprintf(stderr, message, ap); 53 | va_end(ap); 54 | fprintf(stderr,"\n"); 55 | 56 | } 57 | 58 | void EM_reset(string fname) 59 | { 60 | anyErrors=FALSE; fileName=fname; lineNum=1; 61 | linePos=intList(0,NULL); 62 | yyin = fopen(fname,"r"); 63 | if (!yyin) {EM_error(0,"cannot open"); exit(1);} 64 | } 65 | 66 | -------------------------------------------------------------------------------- /chap3/errormsg.h: -------------------------------------------------------------------------------- 1 | extern bool EM_anyErrors; 2 | 3 | void EM_newline(void); 4 | 5 | extern int EM_tokPos; 6 | 7 | void EM_error(int, string,...); 8 | void EM_impossible(string,...); 9 | void EM_reset(string filename); 10 | -------------------------------------------------------------------------------- /chap3/lex.yy.c: -------------------------------------------------------------------------------- 1 | # include "stdio.h" 2 | # define U(x) ((x)&0377) 3 | # define NLSTATE yyprevious=YYNEWLINE 4 | # define BEGIN yybgin = yysvec + 1 + 5 | # define INITIAL 0 6 | # define YYLERR yysvec 7 | # define YYSTATE (yyestate-yysvec-1) 8 | # define YYOPTIM 1 9 | # define YYLMAX 200 10 | # define output(c) putc(c,yyout) 11 | # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) 12 | # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} 13 | # define yymore() (yymorfg=1) 14 | # define ECHO fprintf(yyout, "%s",yytext) 15 | # define REJECT { nstr = yyreject(); goto yyfussy;} 16 | int yyleng; extern unsigned char yytext[]; 17 | int yymorfg; 18 | extern unsigned char *yysptr, yysbuf[]; 19 | int yytchar; 20 | FILE *yyin = {stdin}, *yyout = {stdout}; 21 | extern int yylineno; 22 | struct yysvf { 23 | struct yywork *yystoff; 24 | struct yysvf *yyother; 25 | int *yystops;}; 26 | struct yysvf *yyestate; 27 | extern struct yysvf yysvec[], *yybgin; 28 | /* Copyright (c) 1997 Andrew W. Appel. Licensed software: see LICENSE file */ 29 | #include 30 | #include "util.h" 31 | #include "symbol.h" 32 | #include "absyn.h" 33 | #include "y.tab.h" 34 | #include "errormsg.h" 35 | 36 | static int comLevel=0; 37 | 38 | #define STRINGMAX 1024 39 | char stringbuild[STRINGMAX+1]; 40 | int stringindex=0; 41 | 42 | static void append(char c) 43 | { if (stringindex= 0) 80 | yyfussy: switch(nstr){ 81 | case 0: 82 | if(yywrap()) return(0); break; 83 | case 1: 84 | {adjust(); continue;} 85 | break; 86 | case 2: 87 | {adjust(); EM_newline(); continue;} 88 | break; 89 | case 3: 90 | {adjust(); return COMMA;} 91 | break; 92 | case 4: 93 | {adjust(); return LBRACE;} 94 | break; 95 | case 5: 96 | {adjust(); return RBRACE;} 97 | break; 98 | case 6: 99 | {adjust(); return LBRACK;} 100 | break; 101 | case 7: 102 | {adjust(); return RBRACK;} 103 | break; 104 | case 8: 105 | {adjust(); return COLON;} 106 | break; 107 | case 9: 108 | {adjust(); return SEMICOLON;} 109 | break; 110 | case 10: 111 | {adjust(); return LPAREN;} 112 | break; 113 | case 11: 114 | {adjust(); return RPAREN;} 115 | break; 116 | case 12: 117 | {adjust(); return DOT;} 118 | break; 119 | case 13: 120 | {adjust(); return PLUS;} 121 | break; 122 | case 14: 123 | {adjust(); return MINUS;} 124 | break; 125 | case 15: 126 | {adjust(); return TIMES;} 127 | break; 128 | case 16: 129 | {adjust(); return DIVIDE;} 130 | break; 131 | case 17: 132 | {adjust(); return AND;} 133 | break; 134 | case 18: 135 | {adjust(); return OR;} 136 | break; 137 | case 19: 138 | {adjust(); return ASSIGN;} 139 | break; 140 | case 20: 141 | {adjust(); return EQ;} 142 | break; 143 | case 21: 144 | {adjust(); return NEQ;} 145 | break; 146 | case 22: 147 | {adjust(); return GT;} 148 | break; 149 | case 23: 150 | {adjust(); return LT;} 151 | break; 152 | case 24: 153 | {adjust(); return GE;} 154 | break; 155 | case 25: 156 | {adjust(); return LE;} 157 | break; 158 | case 26: 159 | {adjust(); return FOR;} 160 | break; 161 | case 27: 162 | {adjust(); return WHILE;} 163 | break; 164 | case 28: 165 | {adjust(); return BREAK;} 166 | break; 167 | case 29: 168 | {adjust(); return LET;} 169 | break; 170 | case 30: 171 | {adjust(); return IN;} 172 | break; 173 | case 31: 174 | {adjust(); return NIL;} 175 | break; 176 | case 32: 177 | {adjust(); return TO;} 178 | break; 179 | case 33: 180 | {adjust(); return END;} 181 | break; 182 | case 34: 183 | {adjust(); return FUNCTION;} 184 | break; 185 | case 35: 186 | {adjust(); return VAR;} 187 | break; 188 | case 36: 189 | {adjust(); return TYPE;} 190 | break; 191 | case 37: 192 | {adjust(); return ARRAY;} 193 | break; 194 | case 38: 195 | {adjust(); return IF;} 196 | break; 197 | case 39: 198 | {adjust(); return THEN;} 199 | break; 200 | case 40: 201 | {adjust(); return ELSE;} 202 | break; 203 | case 41: 204 | {adjust(); return DO;} 205 | break; 206 | case 42: 207 | {adjust(); return OF;} 208 | break; 209 | case 43: 210 | {adjust(); yylval.sval = String((char*)yytext); return ID;} 211 | break; 212 | case 44: 213 | {adjust(); yylval.ival=atoi(yytext); return INT;} 214 | break; 215 | case 45: 216 | {adjust(); BEGIN S; continue;} 217 | break; 218 | case 46: 219 | {adjust(); BEGIN A; comLevel = 1; continue;} 220 | break; 221 | case 47: 222 | {adjust(); EM_error(EM_tokPos,"unmatched close comment"); 223 | continue;} 224 | break; 225 | case 48: 226 | {adjust(); EM_error(EM_tokPos,"non-Ascii character"); 227 | continue;} 228 | break; 229 | case 49: 230 | {adjust(); EM_error(EM_tokPos,"illegal token"); 231 | continue;} 232 | break; 233 | case 50: 234 | {adjust(); comLevel++; continue;} 235 | break; 236 | case 51: 237 | {adjust(); EM_newline(); continue;} 238 | break; 239 | case 52: 240 | {adjust(); comLevel--; 241 | if (comLevel==0) {BEGIN INITIAL;} 242 | continue;} 243 | break; 244 | case 53: 245 | {adjust(); continue;} 246 | break; 247 | case 54: 248 | {adjust(); BEGIN INITIAL; 249 | yylval.sval=getstring(); 250 | return STRING;} 251 | break; 252 | case 55: 253 | {adjust(); EM_error (EM_tokPos,"unclosed string"); 254 | EM_newline(); 255 | BEGIN INITIAL; 256 | yylval.sval=getstring(); 257 | return STRING;} 258 | break; 259 | case 56: 260 | {adjust(); EM_newline(); BEGIN F; continue;} 261 | break; 262 | case 57: 263 | {adjust(); BEGIN F; continue;} 264 | break; 265 | case 58: 266 | {adjust(); append(*yytext); continue;} 267 | break; 268 | case 59: 269 | {adjust(); EM_newline(); continue;} 270 | break; 271 | case 60: 272 | {adjust(); continue;} 273 | break; 274 | case 61: 275 | {adjust(); BEGIN S; continue;} 276 | break; 277 | case 62: 278 | {adjust(); EM_error(EM_tokPos, "unclosed string"); 279 | BEGIN INITIAL; 280 | yylval.sval=getstring(); 281 | return STRING;} 282 | break; 283 | case 63: 284 | {adjust(); append('\t'); continue;} 285 | break; 286 | case 64: 287 | {adjust(); append('\n'); continue;} 288 | break; 289 | case 65: 290 | {adjust(); append('\\'); continue;} 291 | break; 292 | case 66: 293 | {adjust(); append(yytext[1]); continue;} 294 | break; 295 | case 67: 296 | {adjust(); append(yytext[2]-'@'); 297 | continue;} 298 | break; 299 | case 68: 300 | {int x = yytext[1]*100 + yytext[2]*10 + yytext[3] - 301 | ('0' * 111); 302 | adjust(); 303 | if (x>255) 304 | EM_error(EM_tokPos, "illegal ascii escape"); 305 | else append(x); 306 | continue; 307 | } 308 | break; 309 | case 69: 310 | {adjust(); EM_error(EM_tokPos, "illegal string escape"); 311 | continue;} 312 | break; 313 | case -1: 314 | break; 315 | default: 316 | fprintf(yyout,"bad switch yylook %d",nstr); 317 | } return(0); } 318 | /* end of yylex */ 319 | int yyvstop[] = { 320 | 0, 321 | 322 | 1, 323 | 60, 324 | 0, 325 | 326 | 1, 327 | 60, 328 | 0, 329 | 330 | 1, 331 | 60, 332 | 0, 333 | 334 | 1, 335 | 60, 336 | 0, 337 | 338 | 1, 339 | 60, 340 | 0, 341 | 342 | 1, 343 | 60, 344 | 0, 345 | 346 | 1, 347 | 60, 348 | 0, 349 | 350 | 1, 351 | 60, 352 | 0, 353 | 354 | 49, 355 | 0, 356 | 357 | 1, 358 | 49, 359 | 0, 360 | 361 | 2, 362 | 0, 363 | 364 | 45, 365 | 49, 366 | 0, 367 | 368 | 17, 369 | 49, 370 | 0, 371 | 372 | 10, 373 | 49, 374 | 0, 375 | 376 | 11, 377 | 49, 378 | 0, 379 | 380 | 15, 381 | 49, 382 | 0, 383 | 384 | 13, 385 | 49, 386 | 0, 387 | 388 | 3, 389 | 49, 390 | 0, 391 | 392 | 14, 393 | 49, 394 | 0, 395 | 396 | 12, 397 | 49, 398 | 0, 399 | 400 | 16, 401 | 49, 402 | 0, 403 | 404 | 44, 405 | 49, 406 | 0, 407 | 408 | 8, 409 | 49, 410 | 0, 411 | 412 | 9, 413 | 49, 414 | 0, 415 | 416 | 23, 417 | 49, 418 | 0, 419 | 420 | 20, 421 | 49, 422 | 0, 423 | 424 | 22, 425 | 49, 426 | 0, 427 | 428 | 43, 429 | 49, 430 | 0, 431 | 432 | 6, 433 | 49, 434 | 0, 435 | 436 | 7, 437 | 49, 438 | 0, 439 | 440 | 43, 441 | 49, 442 | 0, 443 | 444 | 43, 445 | 49, 446 | 0, 447 | 448 | 43, 449 | 49, 450 | 0, 451 | 452 | 43, 453 | 49, 454 | 0, 455 | 456 | 43, 457 | 49, 458 | 0, 459 | 460 | 43, 461 | 48, 462 | 49, 463 | 0, 464 | 465 | 43, 466 | 49, 467 | 0, 468 | 469 | 43, 470 | 49, 471 | 0, 472 | 473 | 43, 474 | 49, 475 | 0, 476 | 477 | 43, 478 | 49, 479 | 0, 480 | 481 | 43, 482 | 49, 483 | 0, 484 | 485 | 43, 486 | 49, 487 | 0, 488 | 489 | 43, 490 | 49, 491 | 0, 492 | 493 | 4, 494 | 49, 495 | 0, 496 | 497 | 18, 498 | 49, 499 | 0, 500 | 501 | 5, 502 | 49, 503 | 0, 504 | 505 | 53, 506 | 0, 507 | 508 | 51, 509 | 0, 510 | 511 | 53, 512 | 0, 513 | 514 | 53, 515 | 0, 516 | 517 | 58, 518 | 0, 519 | 520 | 55, 521 | 0, 522 | 523 | 54, 524 | 58, 525 | 0, 526 | 527 | 58, 528 | 69, 529 | 0, 530 | 531 | 62, 532 | 0, 533 | 534 | 60, 535 | 62, 536 | 0, 537 | 538 | 59, 539 | 0, 540 | 541 | 61, 542 | 62, 543 | 0, 544 | 545 | 1, 546 | 0, 547 | 548 | 47, 549 | 0, 550 | 551 | 46, 552 | 0, 553 | 554 | 44, 555 | 0, 556 | 557 | 19, 558 | 0, 559 | 560 | 25, 561 | 0, 562 | 563 | 21, 564 | 0, 565 | 566 | 24, 567 | 0, 568 | 569 | 43, 570 | 0, 571 | 572 | 43, 573 | 0, 574 | 575 | 43, 576 | 0, 577 | 578 | 41, 579 | 43, 580 | 0, 581 | 582 | 43, 583 | 0, 584 | 585 | 43, 586 | 0, 587 | 588 | 43, 589 | 0, 590 | 591 | 43, 592 | 0, 593 | 594 | 38, 595 | 43, 596 | 0, 597 | 598 | 30, 599 | 43, 600 | 0, 601 | 602 | 43, 603 | 0, 604 | 605 | 43, 606 | 0, 607 | 608 | 42, 609 | 43, 610 | 0, 611 | 612 | 43, 613 | 0, 614 | 615 | 32, 616 | 43, 617 | 0, 618 | 619 | 43, 620 | 0, 621 | 622 | 43, 623 | 0, 624 | 625 | 43, 626 | 0, 627 | 628 | 52, 629 | 0, 630 | 631 | 50, 632 | 0, 633 | 634 | 57, 635 | 0, 636 | 637 | 56, 638 | 0, 639 | 640 | 66, 641 | 0, 642 | 643 | 65, 644 | 0, 645 | 646 | 64, 647 | 0, 648 | 649 | 63, 650 | 0, 651 | 652 | 60, 653 | 0, 654 | 655 | 43, 656 | 0, 657 | 658 | 43, 659 | 0, 660 | 661 | 43, 662 | 0, 663 | 664 | 33, 665 | 43, 666 | 0, 667 | 668 | 26, 669 | 43, 670 | 0, 671 | 672 | 43, 673 | 0, 674 | 675 | 29, 676 | 43, 677 | 0, 678 | 679 | 31, 680 | 43, 681 | 0, 682 | 683 | 43, 684 | 0, 685 | 686 | 43, 687 | 0, 688 | 689 | 35, 690 | 43, 691 | 0, 692 | 693 | 43, 694 | 0, 695 | 696 | 67, 697 | 0, 698 | 699 | 43, 700 | 0, 701 | 702 | 43, 703 | 0, 704 | 705 | 40, 706 | 43, 707 | 0, 708 | 709 | 43, 710 | 0, 711 | 712 | 39, 713 | 43, 714 | 0, 715 | 716 | 36, 717 | 43, 718 | 0, 719 | 720 | 43, 721 | 0, 722 | 723 | 37, 724 | 43, 725 | 0, 726 | 727 | 28, 728 | 43, 729 | 0, 730 | 731 | 43, 732 | 0, 733 | 734 | 27, 735 | 43, 736 | 0, 737 | 738 | 43, 739 | 0, 740 | 741 | 68, 742 | 0, 743 | 744 | 43, 745 | 0, 746 | 747 | 34, 748 | 43, 749 | 0, 750 | 0}; 751 | # define YYTYPE unsigned char 752 | struct yywork { YYTYPE verify, advance; } yycrank[] = { 753 | 0,0, 0,0, 1,9, 0,0, 754 | 0,0, 0,0, 0,0, 0,0, 755 | 0,0, 0,0, 1,10, 1,11, 756 | 0,0, 10,59, 0,0, 56,95, 757 | 0,0, 0,0, 0,0, 0,0, 758 | 0,0, 0,0, 0,0, 0,0, 759 | 0,0, 0,0, 0,0, 0,0, 760 | 0,0, 0,0, 0,0, 0,0, 761 | 0,0, 0,0, 0,0, 1,12, 762 | 10,59, 6,53, 56,95, 1,13, 763 | 0,0, 1,14, 1,15, 1,16, 764 | 1,17, 1,18, 1,19, 1,20, 765 | 1,21, 1,22, 4,49, 16,60, 766 | 21,61, 49,85, 50,86, 4,50, 767 | 0,0, 0,0, 0,0, 1,23, 768 | 1,24, 1,25, 1,26, 1,27, 769 | 23,63, 1,9, 1,28, 22,62, 770 | 22,62, 22,62, 22,62, 22,62, 771 | 22,62, 22,62, 22,62, 22,62, 772 | 22,62, 25,64, 25,65, 27,66, 773 | 0,0, 7,55, 0,0, 0,0, 774 | 0,0, 0,0, 0,0, 0,0, 775 | 0,0, 7,56, 7,57, 0,0, 776 | 1,29, 8,58, 1,30, 6,54, 777 | 1,9, 90,108, 1,31, 1,32, 778 | 1,28, 1,33, 1,34, 1,35, 779 | 1,28, 1,36, 1,37, 1,28, 780 | 1,28, 1,38, 1,28, 1,39, 781 | 1,40, 1,28, 1,28, 1,28, 782 | 1,28, 1,41, 1,28, 1,42, 783 | 1,43, 1,28, 1,28, 1,28, 784 | 1,44, 1,45, 1,46, 2,12, 785 | 7,55, 31,68, 32,69, 2,13, 786 | 33,70, 2,14, 2,15, 2,16, 787 | 2,17, 2,18, 2,19, 2,20, 788 | 2,21, 34,71, 35,73, 34,72, 789 | 7,55, 7,55, 38,77, 39,78, 790 | 35,74, 37,75, 40,79, 2,23, 791 | 2,24, 2,25, 2,26, 2,27, 792 | 41,80, 37,76, 42,83, 43,84, 793 | 68,96, 69,97, 71,98, 41,81, 794 | 72,99, 73,100, 74,101, 77,102, 795 | 78,103, 80,104, 82,105, 83,106, 796 | 7,58, 41,82, 84,107, 7,55, 797 | 96,110, 7,55, 97,111, 3,47, 798 | 98,112, 101,113, 104,114, 105,115, 799 | 2,29, 107,116, 2,30, 3,47, 800 | 3,48, 110,118, 111,119, 2,32, 801 | 2,28, 2,33, 2,34, 2,35, 802 | 2,28, 2,36, 2,37, 2,28, 803 | 2,28, 2,38, 2,28, 2,39, 804 | 2,40, 2,28, 2,28, 2,28, 805 | 2,28, 2,41, 2,28, 2,42, 806 | 2,43, 2,28, 2,28, 2,28, 807 | 2,44, 2,45, 2,46, 5,51, 808 | 3,49, 113,120, 116,121, 117,122, 809 | 120,123, 3,50, 3,47, 5,51, 810 | 5,52, 108,117, 108,117, 108,117, 811 | 108,117, 108,117, 108,117, 108,117, 812 | 108,117, 108,117, 108,117, 123,125, 813 | 125,126, 0,0, 3,47, 3,47, 814 | 0,0, 0,0, 0,0, 0,0, 815 | 0,0, 0,0, 0,0, 0,0, 816 | 5,53, 122,124, 122,124, 122,124, 817 | 122,124, 122,124, 122,124, 122,124, 818 | 122,124, 122,124, 122,124, 0,0, 819 | 0,0, 0,0, 5,51, 0,0, 820 | 0,0, 0,0, 0,0, 0,0, 821 | 0,0, 3,47, 0,0, 3,47, 822 | 0,0, 0,0, 0,0, 0,0, 823 | 0,0, 0,0, 5,51, 5,51, 824 | 0,0, 0,0, 0,0, 0,0, 825 | 0,0, 0,0, 0,0, 0,0, 826 | 0,0, 0,0, 0,0, 0,0, 827 | 0,0, 0,0, 0,0, 28,67, 828 | 28,67, 28,67, 28,67, 28,67, 829 | 28,67, 28,67, 28,67, 28,67, 830 | 28,67, 0,0, 5,54, 0,0, 831 | 0,0, 5,51, 0,0, 5,51, 832 | 28,67, 28,67, 28,67, 28,67, 833 | 28,67, 28,67, 28,67, 28,67, 834 | 28,67, 28,67, 28,67, 28,67, 835 | 28,67, 28,67, 28,67, 28,67, 836 | 28,67, 28,67, 28,67, 28,67, 837 | 28,67, 28,67, 28,67, 28,67, 838 | 28,67, 28,67, 0,0, 0,0, 839 | 0,0, 0,0, 28,67, 0,0, 840 | 28,67, 28,67, 28,67, 28,67, 841 | 28,67, 28,67, 28,67, 28,67, 842 | 28,67, 28,67, 28,67, 28,67, 843 | 28,67, 28,67, 28,67, 28,67, 844 | 28,67, 28,67, 28,67, 28,67, 845 | 28,67, 28,67, 28,67, 28,67, 846 | 28,67, 28,67, 54,87, 54,88, 847 | 0,0, 0,0, 0,0, 0,0, 848 | 0,0, 0,0, 0,0, 0,0, 849 | 0,0, 0,0, 0,0, 0,0, 850 | 0,0, 0,0, 0,0, 0,0, 851 | 0,0, 0,0, 0,0, 0,0, 852 | 0,0, 54,87, 0,0, 54,89, 853 | 0,0, 0,0, 0,0, 0,0, 854 | 0,0, 0,0, 0,0, 0,0, 855 | 0,0, 0,0, 0,0, 0,0, 856 | 0,0, 54,90, 54,90, 54,90, 857 | 54,90, 54,90, 54,90, 54,90, 858 | 54,90, 54,90, 54,90, 92,109, 859 | 92,109, 92,109, 92,109, 92,109, 860 | 92,109, 92,109, 92,109, 92,109, 861 | 92,109, 92,109, 92,109, 92,109, 862 | 92,109, 92,109, 92,109, 92,109, 863 | 92,109, 92,109, 92,109, 92,109, 864 | 92,109, 92,109, 92,109, 92,109, 865 | 92,109, 92,109, 92,109, 92,109, 866 | 92,109, 92,109, 92,109, 0,0, 867 | 0,0, 54,91, 0,0, 54,92, 868 | 0,0, 0,0, 0,0, 0,0, 869 | 0,0, 0,0, 0,0, 0,0, 870 | 0,0, 0,0, 0,0, 0,0, 871 | 0,0, 0,0, 0,0, 54,93, 872 | 0,0, 0,0, 0,0, 0,0, 873 | 0,0, 54,94, 0,0, 0,0, 874 | 0,0}; 875 | struct yysvf yysvec[] = { 876 | 0, 0, 0, 877 | yycrank+-1, 0, yyvstop+1, 878 | yycrank+-93, yysvec+1, yyvstop+4, 879 | yycrank+-178, 0, yyvstop+7, 880 | yycrank+-8, yysvec+3, yyvstop+10, 881 | yycrank+-218, 0, yyvstop+13, 882 | yycrank+-3, yysvec+5, yyvstop+16, 883 | yycrank+-80, 0, yyvstop+19, 884 | yycrank+-1, yysvec+7, yyvstop+22, 885 | yycrank+0, 0, yyvstop+25, 886 | yycrank+4, 0, yyvstop+27, 887 | yycrank+0, 0, yyvstop+30, 888 | yycrank+0, 0, yyvstop+32, 889 | yycrank+0, 0, yyvstop+35, 890 | yycrank+0, 0, yyvstop+38, 891 | yycrank+0, 0, yyvstop+41, 892 | yycrank+4, 0, yyvstop+44, 893 | yycrank+0, 0, yyvstop+47, 894 | yycrank+0, 0, yyvstop+50, 895 | yycrank+0, 0, yyvstop+53, 896 | yycrank+0, 0, yyvstop+56, 897 | yycrank+10, 0, yyvstop+59, 898 | yycrank+19, 0, yyvstop+62, 899 | yycrank+3, 0, yyvstop+65, 900 | yycrank+0, 0, yyvstop+68, 901 | yycrank+16, 0, yyvstop+71, 902 | yycrank+0, 0, yyvstop+74, 903 | yycrank+18, 0, yyvstop+77, 904 | yycrank+251, 0, yyvstop+80, 905 | yycrank+0, 0, yyvstop+83, 906 | yycrank+0, 0, yyvstop+86, 907 | yycrank+15, yysvec+28, yyvstop+89, 908 | yycrank+16, yysvec+28, yyvstop+92, 909 | yycrank+21, yysvec+28, yyvstop+95, 910 | yycrank+33, yysvec+28, yyvstop+98, 911 | yycrank+31, yysvec+28, yyvstop+101, 912 | yycrank+0, yysvec+28, yyvstop+104, 913 | yycrank+47, yysvec+28, yyvstop+108, 914 | yycrank+45, yysvec+28, yyvstop+111, 915 | yycrank+42, yysvec+28, yyvstop+114, 916 | yycrank+48, yysvec+28, yyvstop+117, 917 | yycrank+52, yysvec+28, yyvstop+120, 918 | yycrank+61, yysvec+28, yyvstop+123, 919 | yycrank+55, yysvec+28, yyvstop+126, 920 | yycrank+0, 0, yyvstop+129, 921 | yycrank+0, 0, yyvstop+132, 922 | yycrank+0, 0, yyvstop+135, 923 | yycrank+0, 0, yyvstop+138, 924 | yycrank+0, 0, yyvstop+140, 925 | yycrank+6, 0, yyvstop+142, 926 | yycrank+12, 0, yyvstop+144, 927 | yycrank+0, 0, yyvstop+146, 928 | yycrank+0, 0, yyvstop+148, 929 | yycrank+0, 0, yyvstop+150, 930 | yycrank+365, 0, yyvstop+153, 931 | yycrank+0, 0, yyvstop+156, 932 | yycrank+6, 0, yyvstop+158, 933 | yycrank+0, 0, yyvstop+161, 934 | yycrank+0, 0, yyvstop+163, 935 | yycrank+0, yysvec+10, yyvstop+166, 936 | yycrank+0, 0, yyvstop+168, 937 | yycrank+0, 0, yyvstop+170, 938 | yycrank+0, yysvec+22, yyvstop+172, 939 | yycrank+0, 0, yyvstop+174, 940 | yycrank+0, 0, yyvstop+176, 941 | yycrank+0, 0, yyvstop+178, 942 | yycrank+0, 0, yyvstop+180, 943 | yycrank+0, yysvec+28, yyvstop+182, 944 | yycrank+46, yysvec+28, yyvstop+184, 945 | yycrank+60, yysvec+28, yyvstop+186, 946 | yycrank+0, yysvec+28, yyvstop+188, 947 | yycrank+47, yysvec+28, yyvstop+191, 948 | yycrank+64, yysvec+28, yyvstop+193, 949 | yycrank+51, yysvec+28, yyvstop+195, 950 | yycrank+56, yysvec+28, yyvstop+197, 951 | yycrank+0, yysvec+28, yyvstop+199, 952 | yycrank+0, yysvec+28, yyvstop+202, 953 | yycrank+51, yysvec+28, yyvstop+205, 954 | yycrank+60, yysvec+28, yyvstop+207, 955 | yycrank+0, yysvec+28, yyvstop+209, 956 | yycrank+68, yysvec+28, yyvstop+212, 957 | yycrank+0, yysvec+28, yyvstop+214, 958 | yycrank+58, yysvec+28, yyvstop+217, 959 | yycrank+57, yysvec+28, yyvstop+219, 960 | yycrank+69, yysvec+28, yyvstop+221, 961 | yycrank+0, 0, yyvstop+223, 962 | yycrank+0, 0, yyvstop+225, 963 | yycrank+0, 0, yyvstop+227, 964 | yycrank+0, 0, yyvstop+229, 965 | yycrank+0, 0, yyvstop+231, 966 | yycrank+5, 0, 0, 967 | yycrank+0, 0, yyvstop+233, 968 | yycrank+359, 0, 0, 969 | yycrank+0, 0, yyvstop+235, 970 | yycrank+0, 0, yyvstop+237, 971 | yycrank+0, yysvec+56, yyvstop+239, 972 | yycrank+79, yysvec+28, yyvstop+241, 973 | yycrank+81, yysvec+28, yyvstop+243, 974 | yycrank+79, yysvec+28, yyvstop+245, 975 | yycrank+0, yysvec+28, yyvstop+247, 976 | yycrank+0, yysvec+28, yyvstop+250, 977 | yycrank+82, yysvec+28, yyvstop+253, 978 | yycrank+0, yysvec+28, yyvstop+255, 979 | yycrank+0, yysvec+28, yyvstop+258, 980 | yycrank+72, yysvec+28, yyvstop+261, 981 | yycrank+82, yysvec+28, yyvstop+263, 982 | yycrank+0, yysvec+28, yyvstop+265, 983 | yycrank+77, yysvec+28, yyvstop+268, 984 | yycrank+181, 0, 0, 985 | yycrank+0, 0, yyvstop+270, 986 | yycrank+68, yysvec+28, yyvstop+272, 987 | yycrank+83, yysvec+28, yyvstop+274, 988 | yycrank+0, yysvec+28, yyvstop+276, 989 | yycrank+105, yysvec+28, yyvstop+279, 990 | yycrank+0, yysvec+28, yyvstop+281, 991 | yycrank+0, yysvec+28, yyvstop+284, 992 | yycrank+121, yysvec+28, yyvstop+287, 993 | yycrank+131, 0, 0, 994 | yycrank+0, yysvec+28, yyvstop+289, 995 | yycrank+0, yysvec+28, yyvstop+292, 996 | yycrank+119, yysvec+28, yyvstop+295, 997 | yycrank+0, yysvec+28, yyvstop+297, 998 | yycrank+205, 0, 0, 999 | yycrank+128, yysvec+28, yyvstop+300, 1000 | yycrank+0, 0, yyvstop+302, 1001 | yycrank+130, yysvec+28, yyvstop+304, 1002 | yycrank+0, yysvec+28, yyvstop+306, 1003 | 0, 0, 0}; 1004 | struct yywork *yytop = yycrank+481; 1005 | struct yysvf *yybgin = yysvec+1; 1006 | unsigned char yymatch[] = { 1007 | 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1008 | 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 1009 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1010 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1011 | 011 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1012 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1013 | '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , 1014 | '0' ,'0' ,01 ,01 ,01 ,01 ,01 ,01 , 1015 | '@' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 1016 | 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 1017 | 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 1018 | 'A' ,'A' ,'A' ,'@' ,'@' ,'@' ,'@' ,'_' , 1019 | 01 ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 1020 | 'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 1021 | 'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 1022 | 'a' ,'a' ,'a' ,01 ,01 ,01 ,01 ,01 , 1023 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1024 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1025 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1026 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1027 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1028 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1029 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1030 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1031 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1032 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1033 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1034 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1035 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1036 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1037 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1038 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1039 | 0}; 1040 | unsigned char yyextra[] = { 1041 | 0,0,0,0,0,0,0,0, 1042 | 0,0,0,0,0,0,0,0, 1043 | 0,0,0,0,0,0,0,0, 1044 | 0,0,0,0,0,0,0,0, 1045 | 0,0,0,0,0,0,0,0, 1046 | 0,0,0,0,0,0,0,0, 1047 | 0,0,0,0,0,0,0,0, 1048 | 0,0,0,0,0,0,0,0, 1049 | 0,0,0,0,0,0,0,0, 1050 | 0}; 1051 | /* 1052 | * (c) Copyright 1990, OPEN SOFTWARE FOUNDATION, INC. 1053 | * ALL RIGHTS RESERVED 1054 | */ 1055 | /* 1056 | * OSF/1 Release 1.0 1057 | */ 1058 | /* 1059 | # 1060 | # IBM CONFIDENTIAL 1061 | # Copyright International Business Machines Corp. 1989 1062 | # Unpublished Work 1063 | # All Rights Reserved 1064 | # Licensed Material - Property of IBM 1065 | # 1066 | # 1067 | # US Government Users Restricted Rights - Use, duplication or 1068 | # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 1069 | # 1070 | */ 1071 | /* @(#)ncform 1.3 com/lib/l,3.1,8951 9/7/89 18:48:47 */ 1072 | int yylineno =1; 1073 | # define YYU(x) x 1074 | # define NLSTATE yyprevious=YYNEWLINE 1075 | unsigned char yytext[YYLMAX]; 1076 | struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; 1077 | unsigned char yysbuf[YYLMAX]; 1078 | unsigned char *yysptr = yysbuf; 1079 | int *yyfnd; 1080 | extern struct yysvf *yyestate; 1081 | int yyprevious = YYNEWLINE; 1082 | yylook(){ 1083 | register struct yysvf *yystate, **lsp; 1084 | register struct yywork *yyt; 1085 | struct yysvf *yyz; 1086 | int yych, yyfirst; 1087 | struct yywork *yyr; 1088 | # ifdef LEXDEBUG 1089 | int debug; 1090 | # endif 1091 | unsigned char *yylastch; 1092 | /* start off machines */ 1093 | # ifdef LEXDEBUG 1094 | debug = 0; 1095 | # endif 1096 | yyfirst=1; 1097 | if (!yymorfg) 1098 | yylastch = yytext; 1099 | else { 1100 | yymorfg=0; 1101 | yylastch = yytext+yyleng; 1102 | } 1103 | for(;;){ 1104 | lsp = yylstate; 1105 | yyestate = yystate = yybgin; 1106 | if (yyprevious==YYNEWLINE) yystate++; 1107 | for (;;){ 1108 | # ifdef LEXDEBUG 1109 | if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); 1110 | # endif 1111 | yyt = yystate->yystoff; 1112 | if(yyt == yycrank && !yyfirst){ /* may not be any transitions */ 1113 | yyz = yystate->yyother; 1114 | if(yyz == 0)break; 1115 | if(yyz->yystoff == yycrank)break; 1116 | } 1117 | *yylastch++ = yych = input(); 1118 | yyfirst=0; 1119 | tryagain: 1120 | # ifdef LEXDEBUG 1121 | if(debug){ 1122 | fprintf(yyout,"char "); 1123 | allprint(yych); 1124 | putchar('\n'); 1125 | } 1126 | # endif 1127 | yyr = yyt; 1128 | if ( yyt > yycrank){ 1129 | yyt = yyr + yych; 1130 | if (yyt <= yytop && yyt->verify+yysvec == yystate){ 1131 | if(yyt->advance+yysvec == YYLERR) /* error transitions */ 1132 | {unput(*--yylastch);break;} 1133 | *lsp++ = yystate = yyt->advance+yysvec; 1134 | goto contin; 1135 | } 1136 | } 1137 | # ifdef YYOPTIM 1138 | else if(yyt < yycrank) { /* r < yycrank */ 1139 | yyt = yyr = yycrank+(yycrank-yyt); 1140 | # ifdef LEXDEBUG 1141 | if(debug)fprintf(yyout,"compressed state\n"); 1142 | # endif 1143 | yyt = yyt + yych; 1144 | if(yyt <= yytop && yyt->verify+yysvec == yystate){ 1145 | if(yyt->advance+yysvec == YYLERR) /* error transitions */ 1146 | {unput(*--yylastch);break;} 1147 | *lsp++ = yystate = yyt->advance+yysvec; 1148 | goto contin; 1149 | } 1150 | yyt = yyr + YYU(yymatch[yych]); 1151 | # ifdef LEXDEBUG 1152 | if(debug){ 1153 | fprintf(yyout,"try fall back character "); 1154 | allprint(YYU(yymatch[yych])); 1155 | putchar('\n'); 1156 | } 1157 | # endif 1158 | if(yyt <= yytop && yyt->verify+yysvec == yystate){ 1159 | if(yyt->advance+yysvec == YYLERR) /* error transition */ 1160 | {unput(*--yylastch);break;} 1161 | *lsp++ = yystate = yyt->advance+yysvec; 1162 | goto contin; 1163 | } 1164 | } 1165 | if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ 1166 | # ifdef LEXDEBUG 1167 | if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); 1168 | # endif 1169 | goto tryagain; 1170 | } 1171 | # endif 1172 | else 1173 | {unput(*--yylastch);break;} 1174 | contin: 1175 | # ifdef LEXDEBUG 1176 | if(debug){ 1177 | fprintf(yyout,"state %d char ",yystate-yysvec-1); 1178 | allprint(yych); 1179 | putchar('\n'); 1180 | } 1181 | # endif 1182 | ; 1183 | } 1184 | # ifdef LEXDEBUG 1185 | if(debug){ 1186 | fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); 1187 | allprint(yych); 1188 | putchar('\n'); 1189 | } 1190 | # endif 1191 | while (lsp-- > yylstate){ 1192 | *yylastch-- = 0; 1193 | if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ 1194 | yyolsp = lsp; 1195 | if(yyextra[*yyfnd]){ /* must backup */ 1196 | while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ 1197 | lsp--; 1198 | unput(*yylastch--); 1199 | } 1200 | } 1201 | yyprevious = YYU(*yylastch); 1202 | yylsp = lsp; 1203 | yyleng = yylastch-yytext+1; 1204 | yytext[yyleng] = 0; 1205 | # ifdef LEXDEBUG 1206 | if(debug){ 1207 | fprintf(yyout,"\nmatch "); 1208 | sprint(yytext); 1209 | fprintf(yyout," action %d\n",*yyfnd); 1210 | } 1211 | # endif 1212 | return(*yyfnd++); 1213 | } 1214 | unput(*yylastch); 1215 | } 1216 | if (yytext[0] == 0 /* && feof(yyin) */) 1217 | { 1218 | yysptr=yysbuf; 1219 | return(0); 1220 | } 1221 | yyprevious = yytext[0] = input(); 1222 | if (yyprevious>0) 1223 | output(yyprevious); 1224 | yylastch=yytext; 1225 | # ifdef LEXDEBUG 1226 | if(debug)putchar('\n'); 1227 | # endif 1228 | } 1229 | } 1230 | yyback(p, m) 1231 | int *p; 1232 | { 1233 | if (p==0) return(0); 1234 | while (*p) 1235 | { 1236 | if (*p++ == m) 1237 | return(1); 1238 | } 1239 | return(0); 1240 | } 1241 | /* the following are only used in the lex library */ 1242 | yyinput(){ 1243 | return(input()); 1244 | } 1245 | yyoutput(c) 1246 | int c; { 1247 | output(c); 1248 | } 1249 | yyunput(c) 1250 | int c; { 1251 | unput(c); 1252 | } 1253 | -------------------------------------------------------------------------------- /chap3/makefile: -------------------------------------------------------------------------------- 1 | a.out: parsetest.o y.tab.o lex.yy.o errormsg.o util.o 2 | cc -g parsetest.o y.tab.o lex.yy.o errormsg.o util.o 3 | 4 | parsetest.o: parsetest.c errormsg.h util.h 5 | cc -g -c parsetest.c 6 | 7 | y.tab.o: y.tab.c 8 | cc -g -c y.tab.c 9 | 10 | y.tab.c: tiger.grm 11 | yacc -dv tiger.grm 12 | 13 | y.tab.h: y.tab.c 14 | echo "y.tab.h was created at the same time as y.tab.c" 15 | 16 | errormsg.o: errormsg.c errormsg.h util.h 17 | cc -g -c errormsg.c 18 | 19 | lex.yy.o: lex.yy.c y.tab.h errormsg.h util.h 20 | cc -g -c lex.yy.c 21 | 22 | #lex.yy.c: tiger.lex 23 | # lex tiger.lex 24 | 25 | util.o: util.c util.h 26 | cc -g -c util.c 27 | 28 | clean: 29 | rm -f a.out util.o parsetest.o lex.yy.o errormsg.o y.tab.c y.tab.h y.tab.o 30 | -------------------------------------------------------------------------------- /chap3/parsetest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.h" 3 | #include "errormsg.h" 4 | 5 | extern int yyparse(void); 6 | 7 | void parse(string fname) 8 | {EM_reset(fname); 9 | if (yyparse() == 0) /* parsing worked */ 10 | fprintf(stderr,"Parsing successful!\n"); 11 | else fprintf(stderr,"Parsing failed\n"); 12 | } 13 | 14 | 15 | int main(int argc, char **argv) { 16 | if (argc!=2) {fprintf(stderr,"usage: a.out filename\n"); exit(1);} 17 | parse(argv[1]); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /chap3/tiger.grm: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "util.h" 4 | #include "errormsg.h" 5 | 6 | int yylex(void); /* function prototype */ 7 | 8 | void yyerror(char *s) 9 | { 10 | EM_error(EM_tokPos, "%s", s); 11 | } 12 | %} 13 | 14 | 15 | %union { 16 | int pos; 17 | int ival; 18 | string sval; 19 | } 20 | 21 | %token ID STRING 22 | %token INT 23 | 24 | %token 25 | COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK 26 | LBRACE RBRACE DOT 27 | PLUS MINUS TIMES DIVIDE EQ NEQ LT LE GT GE 28 | AND OR ASSIGN 29 | ARRAY IF THEN ELSE WHILE FOR TO DO LET IN END OF 30 | BREAK NIL 31 | FUNCTION VAR TYPE 32 | 33 | %start program 34 | 35 | %% 36 | 37 | program: exp 38 | 39 | exp: ID 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /chap3/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * util.c - commonly used utility functions. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "util.h" 9 | void *checked_malloc(int len) 10 | {void *p = malloc(len); 11 | if (!p) { 12 | fprintf(stderr,"\nRan out of memory!\n"); 13 | exit(1); 14 | } 15 | return p; 16 | } 17 | 18 | string String(char *s) 19 | {string p = checked_malloc(strlen(s)+1); 20 | strcpy(p,s); 21 | return p; 22 | } 23 | 24 | U_boolList U_BoolList(bool head, U_boolList tail) 25 | { U_boolList list = checked_malloc(sizeof(*list)); 26 | list->head = head; 27 | list->tail = tail; 28 | return list; 29 | } 30 | -------------------------------------------------------------------------------- /chap3/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef char *string; 4 | typedef char bool; 5 | 6 | #define TRUE 1 7 | #define FALSE 0 8 | 9 | void *checked_malloc(int); 10 | string String(char *); 11 | 12 | typedef struct U_boolList_ *U_boolList; 13 | struct U_boolList_ {bool head; U_boolList tail;}; 14 | U_boolList U_BoolList(bool head, U_boolList tail); 15 | 16 | -------------------------------------------------------------------------------- /chap3/y.output: -------------------------------------------------------------------------------- 1 | 2 | state 0 3 | $accept : _program $end 4 | 5 | ID shift 3 6 | . error 7 | 8 | program goto 1 9 | exp goto 2 10 | 11 | state 1 12 | $accept : program_$end 13 | 14 | $end accept 15 | . error 16 | 17 | 18 | state 2 19 | program : exp_ (1) 20 | 21 | . reduce 1 22 | 23 | 24 | state 3 25 | exp : ID_ (2) 26 | 27 | . reduce 2 28 | 29 | 30 | 45/3000 terminals, 2/1000 nonterminals 31 | 3/2000 grammar rules, 4/5000 states 32 | 0 shift/reduce, 0 reduce/reduce conflicts reported 33 | 3/1400 working sets used 34 | memory: states,etc. 30/40000, parser 1/70000 35 | 3/600 distinct lookahead sets 36 | 0 extra closures 37 | 1 shift entries, 1 exceptions 38 | 2 goto entries 39 | 0 entries saved by goto default 40 | Optimizer space used: input 6/40000, output 3/70000 41 | 3 table entries, 0 zero 42 | maximum spread: 257, maximum offset: 257 43 | -------------------------------------------------------------------------------- /chap4/absyn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * absyn.c - Abstract Syntax Functions. Most functions create an instance of an 3 | * abstract syntax rule. 4 | */ 5 | 6 | #include "util.h" 7 | #include "symbol.h" /* symbol table data structures */ 8 | #include "absyn.h" /* abstract syntax data structures */ 9 | 10 | A_var A_SimpleVar(A_pos pos, S_symbol sym) 11 | {A_var p = checked_malloc(sizeof(*p)); 12 | p->kind=A_simpleVar; 13 | p->pos=pos; 14 | p->u.simple=sym; 15 | return p; 16 | } 17 | 18 | A_var A_FieldVar(A_pos pos, A_var var, S_symbol sym) 19 | {A_var p = checked_malloc(sizeof(*p)); 20 | p->kind=A_fieldVar; 21 | p->pos=pos; 22 | p->u.field.var=var; 23 | p->u.field.sym=sym; 24 | return p; 25 | } 26 | 27 | A_var A_SubscriptVar(A_pos pos, A_var var, A_exp exp) 28 | {A_var p = checked_malloc(sizeof(*p)); 29 | p->kind=A_subscriptVar; 30 | p->pos=pos; 31 | p->u.subscript.var=var; 32 | p->u.subscript.exp=exp; 33 | return p; 34 | } 35 | 36 | 37 | A_exp A_VarExp(A_pos pos, A_var var) 38 | {A_exp p = checked_malloc(sizeof(*p)); 39 | p->kind=A_varExp; 40 | p->pos=pos; 41 | p->u.var=var; 42 | return p; 43 | } 44 | 45 | A_exp A_NilExp(A_pos pos) 46 | {A_exp p = checked_malloc(sizeof(*p)); 47 | p->kind=A_nilExp; 48 | p->pos=pos; 49 | return p; 50 | } 51 | 52 | A_exp A_IntExp(A_pos pos, int i) 53 | {A_exp p = checked_malloc(sizeof(*p)); 54 | p->kind=A_intExp; 55 | p->pos=pos; 56 | p->u.intt=i; 57 | return p; 58 | } 59 | 60 | A_exp A_StringExp(A_pos pos, string s) 61 | {A_exp p = checked_malloc(sizeof(*p)); 62 | p->kind=A_stringExp; 63 | p->pos=pos; 64 | p->u.stringg=s; 65 | return p; 66 | } 67 | 68 | A_exp A_CallExp(A_pos pos, S_symbol func, A_expList args) 69 | {A_exp p = checked_malloc(sizeof(*p)); 70 | p->kind=A_callExp; 71 | p->pos=pos; 72 | p->u.call.func=func; 73 | p->u.call.args=args; 74 | return p; 75 | } 76 | 77 | A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right) 78 | {A_exp p = checked_malloc(sizeof(*p)); 79 | p->kind=A_opExp; 80 | p->pos=pos; 81 | p->u.op.oper=oper; 82 | p->u.op.left=left; 83 | p->u.op.right=right; 84 | return p; 85 | } 86 | 87 | A_exp A_RecordExp(A_pos pos, S_symbol typ, A_efieldList fields) 88 | {A_exp p = checked_malloc(sizeof(*p)); 89 | p->kind=A_recordExp; 90 | p->pos=pos; 91 | p->u.record.typ=typ; 92 | p->u.record.fields=fields; 93 | return p; 94 | } 95 | 96 | A_exp A_SeqExp(A_pos pos, A_expList seq) 97 | {A_exp p = checked_malloc(sizeof(*p)); 98 | p->kind=A_seqExp; 99 | p->pos=pos; 100 | p->u.seq=seq; 101 | return p; 102 | } 103 | 104 | A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp) 105 | {A_exp p = checked_malloc(sizeof(*p)); 106 | p->kind=A_assignExp; 107 | p->pos=pos; 108 | p->u.assign.var=var; 109 | p->u.assign.exp=exp; 110 | return p; 111 | } 112 | 113 | A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee) 114 | {A_exp p = checked_malloc(sizeof(*p)); 115 | p->kind=A_ifExp; 116 | p->pos=pos; 117 | p->u.iff.test=test; 118 | p->u.iff.then=then; 119 | p->u.iff.elsee=elsee; 120 | return p; 121 | } 122 | 123 | A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body) 124 | {A_exp p = checked_malloc(sizeof(*p)); 125 | p->kind=A_whileExp; 126 | p->pos=pos; 127 | p->u.whilee.test=test; 128 | p->u.whilee.body=body; 129 | return p; 130 | } 131 | 132 | A_exp A_ForExp(A_pos pos, S_symbol var, A_exp lo, A_exp hi, A_exp body) 133 | {A_exp p = checked_malloc(sizeof(*p)); 134 | p->kind=A_forExp; 135 | p->pos=pos; 136 | p->u.forr.var=var; 137 | p->u.forr.lo=lo; 138 | p->u.forr.hi=hi; 139 | p->u.forr.body=body; 140 | p->u.forr.escape=TRUE; 141 | return p; 142 | } 143 | 144 | A_exp A_BreakExp(A_pos pos) 145 | {A_exp p = checked_malloc(sizeof(*p)); 146 | p->kind=A_breakExp; 147 | p->pos=pos; 148 | return p; 149 | } 150 | 151 | A_exp A_LetExp(A_pos pos, A_decList decs, A_exp body) 152 | {A_exp p = checked_malloc(sizeof(*p)); 153 | p->kind=A_letExp; 154 | p->pos=pos; 155 | p->u.let.decs=decs; 156 | p->u.let.body=body; 157 | return p; 158 | } 159 | 160 | A_exp A_ArrayExp(A_pos pos, S_symbol typ, A_exp size, A_exp init) 161 | {A_exp p = checked_malloc(sizeof(*p)); 162 | p->kind=A_arrayExp; 163 | p->pos=pos; 164 | p->u.array.typ=typ; 165 | p->u.array.size=size; 166 | p->u.array.init=init; 167 | return p; 168 | } 169 | 170 | A_dec A_FunctionDec(A_pos pos, A_fundecList function) 171 | {A_dec p = checked_malloc(sizeof(*p)); 172 | p->kind=A_functionDec; 173 | p->pos=pos; 174 | p->u.function=function; 175 | return p; 176 | } 177 | 178 | A_dec A_VarDec(A_pos pos, S_symbol var, S_symbol typ, A_exp init) 179 | {A_dec p = checked_malloc(sizeof(*p)); 180 | p->kind=A_varDec; 181 | p->pos=pos; 182 | p->u.var.var=var; 183 | p->u.var.typ=typ; 184 | p->u.var.init=init; 185 | p->u.var.escape=TRUE; 186 | return p; 187 | } 188 | 189 | A_dec A_TypeDec(A_pos pos, A_nametyList type) 190 | {A_dec p = checked_malloc(sizeof(*p)); 191 | p->kind=A_typeDec; 192 | p->pos=pos; 193 | p->u.type=type; 194 | return p; 195 | } 196 | 197 | A_ty A_NameTy(A_pos pos, S_symbol name) 198 | {A_ty p = checked_malloc(sizeof(*p)); 199 | p->kind=A_nameTy; 200 | p->pos=pos; 201 | p->u.name=name; 202 | return p; 203 | } 204 | 205 | A_ty A_RecordTy(A_pos pos, A_fieldList record) 206 | {A_ty p = checked_malloc(sizeof(*p)); 207 | p->kind=A_recordTy; 208 | p->pos=pos; 209 | p->u.record=record; 210 | return p; 211 | } 212 | 213 | A_ty A_ArrayTy(A_pos pos, S_symbol array) 214 | {A_ty p = checked_malloc(sizeof(*p)); 215 | p->kind=A_arrayTy; 216 | p->pos=pos; 217 | p->u.array=array; 218 | return p; 219 | } 220 | 221 | A_field A_Field(A_pos pos, S_symbol name, S_symbol typ) 222 | {A_field p = checked_malloc(sizeof(*p)); 223 | p->pos=pos; 224 | p->name=name; 225 | p->typ=typ; 226 | p->escape=TRUE; 227 | return p; 228 | } 229 | 230 | A_fieldList A_FieldList(A_field head, A_fieldList tail) 231 | {A_fieldList p = checked_malloc(sizeof(*p)); 232 | p->head=head; 233 | p->tail=tail; 234 | return p; 235 | } 236 | 237 | A_expList A_ExpList(A_exp head, A_expList tail) 238 | {A_expList p = checked_malloc(sizeof(*p)); 239 | p->head=head; 240 | p->tail=tail; 241 | return p; 242 | } 243 | 244 | A_fundec A_Fundec(A_pos pos, S_symbol name, A_fieldList params, S_symbol result, 245 | A_exp body) 246 | {A_fundec p = checked_malloc(sizeof(*p)); 247 | p->pos=pos; 248 | p->name=name; 249 | p->params=params; 250 | p->result=result; 251 | p->body=body; 252 | return p; 253 | } 254 | 255 | A_fundecList A_FundecList(A_fundec head, A_fundecList tail) 256 | {A_fundecList p = checked_malloc(sizeof(*p)); 257 | p->head=head; 258 | p->tail=tail; 259 | return p; 260 | } 261 | 262 | A_decList A_DecList(A_dec head, A_decList tail) 263 | {A_decList p = checked_malloc(sizeof(*p)); 264 | p->head=head; 265 | p->tail=tail; 266 | return p; 267 | } 268 | 269 | A_namety A_Namety(S_symbol name, A_ty ty) 270 | {A_namety p = checked_malloc(sizeof(*p)); 271 | p->name=name; 272 | p->ty=ty; 273 | return p; 274 | } 275 | 276 | A_nametyList A_NametyList(A_namety head, A_nametyList tail) 277 | {A_nametyList p = checked_malloc(sizeof(*p)); 278 | p->head=head; 279 | p->tail=tail; 280 | return p; 281 | } 282 | 283 | A_efield A_Efield(S_symbol name, A_exp exp) 284 | {A_efield p = checked_malloc(sizeof(*p)); 285 | p->name=name; 286 | p->exp=exp; 287 | return p; 288 | } 289 | 290 | A_efieldList A_EfieldList(A_efield head, A_efieldList tail) 291 | {A_efieldList p = checked_malloc(sizeof(*p)); 292 | p->head=head; 293 | p->tail=tail; 294 | return p; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /chap4/absyn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * absyn.h - Abstract Syntax Header (Chapter 4) 3 | * 4 | * All types and functions declared in this header file begin with "A_" 5 | * Linked list types end with "..list" 6 | */ 7 | 8 | /* Type Definitions */ 9 | 10 | typedef int A_pos; 11 | 12 | typedef struct A_var_ *A_var; 13 | typedef struct A_exp_ *A_exp; 14 | typedef struct A_dec_ *A_dec; 15 | typedef struct A_ty_ *A_ty; 16 | 17 | typedef struct A_decList_ *A_decList; 18 | typedef struct A_expList_ *A_expList; 19 | typedef struct A_field_ *A_field; 20 | typedef struct A_fieldList_ *A_fieldList; 21 | typedef struct A_fundec_ *A_fundec; 22 | typedef struct A_fundecList_ *A_fundecList; 23 | typedef struct A_namety_ *A_namety; 24 | typedef struct A_nametyList_ *A_nametyList; 25 | typedef struct A_efield_ *A_efield; 26 | typedef struct A_efieldList_ *A_efieldList; 27 | 28 | typedef enum {A_plusOp, A_minusOp, A_timesOp, A_divideOp, 29 | A_eqOp, A_neqOp, A_ltOp, A_leOp, A_gtOp, A_geOp} A_oper; 30 | 31 | struct A_var_ 32 | {enum {A_simpleVar, A_fieldVar, A_subscriptVar} kind; 33 | A_pos pos; 34 | union {S_symbol simple; 35 | struct {A_var var; 36 | S_symbol sym;} field; 37 | struct {A_var var; 38 | A_exp exp;} subscript; 39 | } u; 40 | }; 41 | 42 | struct A_exp_ 43 | {enum {A_varExp, A_nilExp, A_intExp, A_stringExp, A_callExp, 44 | A_opExp, A_recordExp, A_seqExp, A_assignExp, A_ifExp, 45 | A_whileExp, A_forExp, A_breakExp, A_letExp, A_arrayExp} kind; 46 | A_pos pos; 47 | union {A_var var; 48 | /* nil; - needs only the pos */ 49 | int intt; 50 | string stringg; 51 | struct {S_symbol func; A_expList args;} call; 52 | struct {A_oper oper; A_exp left; A_exp right;} op; 53 | struct {S_symbol typ; A_efieldList fields;} record; 54 | A_expList seq; 55 | struct {A_var var; A_exp exp;} assign; 56 | struct {A_exp test, then, elsee;} iff; /* elsee is optional */ 57 | struct {A_exp test, body;} whilee; 58 | struct {S_symbol var; A_exp lo,hi,body; bool escape;} forr; 59 | /* breakk; - need only the pos */ 60 | struct {A_decList decs; A_exp body;} let; 61 | struct {S_symbol typ; A_exp size, init;} array; 62 | } u; 63 | }; 64 | 65 | struct A_dec_ 66 | {enum {A_functionDec, A_varDec, A_typeDec} kind; 67 | A_pos pos; 68 | union {A_fundecList function; 69 | /* escape may change after the initial declaration */ 70 | struct {S_symbol var; S_symbol typ; A_exp init; bool escape;} var; 71 | A_nametyList type; 72 | } u; 73 | }; 74 | 75 | struct A_ty_ {enum {A_nameTy, A_recordTy, A_arrayTy} kind; 76 | A_pos pos; 77 | union {S_symbol name; 78 | A_fieldList record; 79 | S_symbol array; 80 | } u; 81 | }; 82 | 83 | /* Linked lists and nodes of lists */ 84 | 85 | struct A_field_ {S_symbol name, typ; A_pos pos; bool escape;}; 86 | struct A_fieldList_ {A_field head; A_fieldList tail;}; 87 | struct A_expList_ {A_exp head; A_expList tail;}; 88 | struct A_fundec_ {A_pos pos; 89 | S_symbol name; A_fieldList params; 90 | S_symbol result; A_exp body;}; 91 | 92 | struct A_fundecList_ {A_fundec head; A_fundecList tail;}; 93 | struct A_decList_ {A_dec head; A_decList tail;}; 94 | struct A_namety_ {S_symbol name; A_ty ty;}; 95 | struct A_nametyList_ {A_namety head; A_nametyList tail;}; 96 | struct A_efield_ {S_symbol name; A_exp exp;}; 97 | struct A_efieldList_ {A_efield head; A_efieldList tail;}; 98 | 99 | 100 | /* Function Prototypes */ 101 | A_var A_SimpleVar(A_pos pos, S_symbol sym); 102 | A_var A_FieldVar(A_pos pos, A_var var, S_symbol sym); 103 | A_var A_SubscriptVar(A_pos pos, A_var var, A_exp exp); 104 | A_exp A_VarExp(A_pos pos, A_var var); 105 | A_exp A_NilExp(A_pos pos); 106 | A_exp A_IntExp(A_pos pos, int i); 107 | A_exp A_StringExp(A_pos pos, string s); 108 | A_exp A_CallExp(A_pos pos, S_symbol func, A_expList args); 109 | A_exp A_OpExp(A_pos pos, A_oper oper, A_exp left, A_exp right); 110 | A_exp A_RecordExp(A_pos pos, S_symbol typ, A_efieldList fields); 111 | A_exp A_SeqExp(A_pos pos, A_expList seq); 112 | A_exp A_AssignExp(A_pos pos, A_var var, A_exp exp); 113 | A_exp A_IfExp(A_pos pos, A_exp test, A_exp then, A_exp elsee); 114 | A_exp A_WhileExp(A_pos pos, A_exp test, A_exp body); 115 | A_exp A_ForExp(A_pos pos, S_symbol var, A_exp lo, A_exp hi, A_exp body); 116 | A_exp A_BreakExp(A_pos pos); 117 | A_exp A_LetExp(A_pos pos, A_decList decs, A_exp body); 118 | A_exp A_ArrayExp(A_pos pos, S_symbol typ, A_exp size, A_exp init); 119 | A_dec A_FunctionDec(A_pos pos, A_fundecList function); 120 | A_dec A_VarDec(A_pos pos, S_symbol var, S_symbol typ, A_exp init); 121 | A_dec A_TypeDec(A_pos pos, A_nametyList type); 122 | A_ty A_NameTy(A_pos pos, S_symbol name); 123 | A_ty A_RecordTy(A_pos pos, A_fieldList record); 124 | A_ty A_ArrayTy(A_pos pos, S_symbol array); 125 | A_field A_Field(A_pos pos, S_symbol name, S_symbol typ); 126 | A_fieldList A_FieldList(A_field head, A_fieldList tail); 127 | A_expList A_ExpList(A_exp head, A_expList tail); 128 | A_fundec A_Fundec(A_pos pos, S_symbol name, A_fieldList params, S_symbol result, 129 | A_exp body); 130 | A_fundecList A_FundecList(A_fundec head, A_fundecList tail); 131 | A_decList A_DecList(A_dec head, A_decList tail); 132 | A_namety A_Namety(S_symbol name, A_ty ty); 133 | A_nametyList A_NametyList(A_namety head, A_nametyList tail); 134 | A_efield A_Efield(S_symbol name, A_exp exp); 135 | A_efieldList A_EfieldList(A_efield head, A_efieldList tail); 136 | -------------------------------------------------------------------------------- /chap4/lex.yy.c: -------------------------------------------------------------------------------- 1 | # include "stdio.h" 2 | # define U(x) ((x)&0377) 3 | # define YYLERR yysvec 4 | # define YYSTATE (yyestate-yysvec-1) 5 | # define YYOPTIM 1 6 | # define YYLMAX 200 7 | # define output(c) putc(c,yyout) 8 | # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) 9 | # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} 10 | int yyleng; extern unsigned char yytext[]; 11 | int yymorfg; 12 | extern unsigned char *yysptr, yysbuf[]; 13 | int yytchar; 14 | FILE *yyin = {stdin}, *yyout = {stdout}; 15 | extern int yylineno; 16 | struct yysvf { 17 | struct yywork *yystoff; 18 | struct yysvf *yyother; 19 | int *yystops;}; 20 | struct yysvf *yyestate; 21 | extern struct yysvf yysvec[], *yybgin; 22 | #include 23 | #include "util.h" 24 | #include "y.tab.h" 25 | #include "errormsg.h" 26 | 27 | static int q3=0; 28 | char q1[1024+1];int q2=0; 29 | static void q4(char c) { if (q2<1024) q1[q2++]= c; else 30 | {EM_error(EM_tokPos,"string too long."); q2=0;} } 31 | static string q5(void) {q1[q2]=0; q2=0; return String(q1); } 32 | 33 | int charPos=1; 34 | 35 | int yywrap(void) 36 | { 37 | if (q3) 38 | EM_error(EM_tokPos,"unclosed comment"); 39 | charPos=1; 40 | return 1; 41 | } 42 | 43 | 44 | void adjust(void) 45 | { 46 | EM_tokPos=charPos; 47 | charPos+=yyleng; 48 | } 49 | 50 | yylex(){ 51 | int nstr; extern int yyprevious; 52 | while((nstr = yylook()) >= 0) 53 | yyfussy: switch(nstr){ 54 | case 0: 55 | if(yywrap()) return(0); break; 56 | case 1: 57 | {adjust(); continue;} 58 | break; 59 | case 2: 60 | {adjust(); EM_newline(); continue;} 61 | break; 62 | case 3: 63 | {adjust(); return COMMA;} 64 | break; 65 | case 4: 66 | {adjust(); return LBRACE;} 67 | break; 68 | case 5: 69 | {adjust(); return RBRACE;} 70 | break; 71 | case 6: 72 | {adjust(); return LBRACK;} 73 | break; 74 | case 7: 75 | {adjust(); return RBRACK;} 76 | break; 77 | case 8: 78 | {adjust(); return COLON;} 79 | break; 80 | case 9: 81 | {adjust(); return SEMICOLON;} 82 | break; 83 | case 10: 84 | {adjust(); return LPAREN;} 85 | break; 86 | case 11: 87 | {adjust(); return RPAREN;} 88 | break; 89 | case 12: 90 | {adjust(); return DOT;} 91 | break; 92 | case 13: 93 | {adjust(); return PLUS;} 94 | break; 95 | case 14: 96 | {adjust(); return MINUS;} 97 | break; 98 | case 15: 99 | {adjust(); return TIMES;} 100 | break; 101 | case 16: 102 | {adjust(); return DIVIDE;} 103 | break; 104 | case 17: 105 | {adjust(); return AND;} 106 | break; 107 | case 18: 108 | {adjust(); return OR;} 109 | break; 110 | case 19: 111 | {adjust(); return ASSIGN;} 112 | break; 113 | case 20: 114 | {adjust(); return EQ;} 115 | break; 116 | case 21: 117 | {adjust(); return NEQ;} 118 | break; 119 | case 22: 120 | {adjust(); return GT;} 121 | break; 122 | case 23: 123 | {adjust(); return LT;} 124 | break; 125 | case 24: 126 | {adjust(); return GE;} 127 | break; 128 | case 25: 129 | {adjust(); return LE;} 130 | break; 131 | case 26: 132 | {adjust(); return FOR;} 133 | break; 134 | case 27: 135 | {adjust(); return WHILE;} 136 | break; 137 | case 28: 138 | {adjust(); return BREAK;} 139 | break; 140 | case 29: 141 | {adjust(); return LET;} 142 | break; 143 | case 30: 144 | {adjust(); return IN;} 145 | break; 146 | case 31: 147 | {adjust(); return NIL;} 148 | break; 149 | case 32: 150 | {adjust(); return TO;} 151 | break; 152 | case 33: 153 | {adjust(); return END;} 154 | break; 155 | case 34: 156 | {adjust(); return FUNCTION;} 157 | break; 158 | case 35: 159 | {adjust(); return VAR;} 160 | break; 161 | case 36: 162 | {adjust(); return TYPE;} 163 | break; 164 | case 37: 165 | {adjust(); return ARRAY;} 166 | break; 167 | case 38: 168 | {adjust(); return IF;} 169 | break; 170 | case 39: 171 | {adjust(); return THEN;} 172 | break; 173 | case 40: 174 | {adjust(); return ELSE;} 175 | break; 176 | case 41: 177 | {adjust(); return DO;} 178 | break; 179 | case 42: 180 | {adjust(); return OF;} 181 | break; 182 | case 43: 183 | {adjust(); yylval.sval = String((char*)yytext); return ID;} 184 | break; 185 | case 44: 186 | {adjust(); yylval.ival=atoi(yytext); return INT;} 187 | break; 188 | case 45: 189 | {adjust(); yybgin = yysvec + 1 + 4; continue;} 190 | break; 191 | case 46: 192 | {adjust(); yybgin = yysvec + 1 + 2; q3 = 1; continue;} 193 | break; 194 | case 47: 195 | {adjust(); EM_error(EM_tokPos,"unmatched close comment"); 196 | continue;} 197 | break; 198 | case 48: 199 | {adjust(); EM_error(EM_tokPos,"non-Ascii character"); 200 | continue;} 201 | break; 202 | case 49: 203 | {adjust(); EM_error(EM_tokPos,"illegal token"); 204 | continue;} 205 | break; 206 | case 50: 207 | {adjust(); q3++; continue;} 208 | break; 209 | case 51: 210 | {adjust(); EM_newline(); continue;} 211 | break; 212 | case 52: 213 | {adjust(); q3--; 214 | if (q3==0) {yybgin = yysvec + 1 + 0;} 215 | continue;} 216 | break; 217 | case 53: 218 | {adjust(); continue;} 219 | break; 220 | case 54: 221 | {adjust(); yybgin = yysvec + 1 + 0; 222 | yylval.sval=q5(); 223 | return STRING;} 224 | break; 225 | case 55: 226 | {adjust(); EM_error (EM_tokPos,"unclosed string"); 227 | EM_newline(); 228 | yybgin = yysvec + 1 + 0; 229 | yylval.sval=q5(); 230 | return STRING;} 231 | break; 232 | case 56: 233 | {adjust(); EM_newline(); yybgin = yysvec + 1 + 6; continue;} 234 | break; 235 | case 57: 236 | {adjust(); yybgin = yysvec + 1 + 6; continue;} 237 | break; 238 | case 58: 239 | {adjust(); q4(*yytext); continue;} 240 | break; 241 | case 59: 242 | {adjust(); EM_newline(); continue;} 243 | break; 244 | case 60: 245 | {adjust(); continue;} 246 | break; 247 | case 61: 248 | {adjust(); yybgin = yysvec + 1 + 4; continue;} 249 | break; 250 | case 62: 251 | {adjust(); EM_error(EM_tokPos, "unclosed string"); 252 | yybgin = yysvec + 1 + 0; 253 | yylval.sval=q5(); 254 | return STRING;} 255 | break; 256 | case 63: 257 | {adjust(); q4('\t'); continue;} 258 | break; 259 | case 64: 260 | {adjust(); q4('\n'); continue;} 261 | break; 262 | case 65: 263 | {adjust(); q4('\\'); continue;} 264 | break; 265 | case 66: 266 | {adjust(); q4(yytext[1]); continue;} 267 | break; 268 | case 67: 269 | {adjust(); q4(yytext[2]-'@'); 270 | continue;} 271 | break; 272 | case 68: 273 | {int x = yytext[1]*100 + yytext[2]*10 + yytext[3] - 274 | ('0' * 111); 275 | adjust(); 276 | if (x>255) 277 | EM_error(EM_tokPos, "illegal ascii escape"); 278 | else q4(x); 279 | continue; 280 | } 281 | break; 282 | case 69: 283 | {adjust(); EM_error(EM_tokPos, "illegal string escape"); 284 | continue;} 285 | break; 286 | case -1: 287 | break; 288 | default: 289 | fprintf(yyout,"bad switch yylook %d",nstr); 290 | } return(0); } 291 | /* end of yylex */ 292 | int yyvstop[] = { 293 | 0, 294 | 295 | 1, 296 | 60, 297 | 0, 298 | 299 | 1, 300 | 60, 301 | 0, 302 | 303 | 1, 304 | 60, 305 | 0, 306 | 307 | 1, 308 | 60, 309 | 0, 310 | 311 | 1, 312 | 60, 313 | 0, 314 | 315 | 1, 316 | 60, 317 | 0, 318 | 319 | 1, 320 | 60, 321 | 0, 322 | 323 | 1, 324 | 60, 325 | 0, 326 | 327 | 49, 328 | 0, 329 | 330 | 1, 331 | 49, 332 | 0, 333 | 334 | 1, 335 | 2, 336 | 0, 337 | 338 | 45, 339 | 49, 340 | 0, 341 | 342 | 17, 343 | 49, 344 | 0, 345 | 346 | 10, 347 | 49, 348 | 0, 349 | 350 | 11, 351 | 49, 352 | 0, 353 | 354 | 15, 355 | 49, 356 | 0, 357 | 358 | 13, 359 | 49, 360 | 0, 361 | 362 | 3, 363 | 49, 364 | 0, 365 | 366 | 14, 367 | 49, 368 | 0, 369 | 370 | 12, 371 | 49, 372 | 0, 373 | 374 | 16, 375 | 49, 376 | 0, 377 | 378 | 44, 379 | 49, 380 | 0, 381 | 382 | 8, 383 | 49, 384 | 0, 385 | 386 | 9, 387 | 49, 388 | 0, 389 | 390 | 23, 391 | 49, 392 | 0, 393 | 394 | 20, 395 | 49, 396 | 0, 397 | 398 | 22, 399 | 49, 400 | 0, 401 | 402 | 43, 403 | 49, 404 | 0, 405 | 406 | 6, 407 | 49, 408 | 0, 409 | 410 | 7, 411 | 49, 412 | 0, 413 | 414 | 43, 415 | 49, 416 | 0, 417 | 418 | 43, 419 | 49, 420 | 0, 421 | 422 | 43, 423 | 49, 424 | 0, 425 | 426 | 43, 427 | 49, 428 | 0, 429 | 430 | 43, 431 | 49, 432 | 0, 433 | 434 | 43, 435 | 48, 436 | 49, 437 | 0, 438 | 439 | 43, 440 | 49, 441 | 0, 442 | 443 | 43, 444 | 49, 445 | 0, 446 | 447 | 43, 448 | 49, 449 | 0, 450 | 451 | 43, 452 | 49, 453 | 0, 454 | 455 | 43, 456 | 49, 457 | 0, 458 | 459 | 43, 460 | 49, 461 | 0, 462 | 463 | 43, 464 | 49, 465 | 0, 466 | 467 | 4, 468 | 49, 469 | 0, 470 | 471 | 18, 472 | 49, 473 | 0, 474 | 475 | 5, 476 | 49, 477 | 0, 478 | 479 | 53, 480 | 0, 481 | 482 | 51, 483 | 0, 484 | 485 | 53, 486 | 0, 487 | 488 | 53, 489 | 0, 490 | 491 | 58, 492 | 0, 493 | 494 | 55, 495 | 0, 496 | 497 | 54, 498 | 58, 499 | 0, 500 | 501 | 58, 502 | 69, 503 | 0, 504 | 505 | 62, 506 | 0, 507 | 508 | 60, 509 | 62, 510 | 0, 511 | 512 | 59, 513 | 60, 514 | 0, 515 | 516 | 61, 517 | 62, 518 | 0, 519 | 520 | 1, 521 | 0, 522 | 523 | 46, 524 | 0, 525 | 526 | 47, 527 | 0, 528 | 529 | 44, 530 | 0, 531 | 532 | 19, 533 | 0, 534 | 535 | 25, 536 | 0, 537 | 538 | 21, 539 | 0, 540 | 541 | 24, 542 | 0, 543 | 544 | 43, 545 | 0, 546 | 547 | 43, 548 | 0, 549 | 550 | 43, 551 | 0, 552 | 553 | 41, 554 | 43, 555 | 0, 556 | 557 | 43, 558 | 0, 559 | 560 | 43, 561 | 0, 562 | 563 | 43, 564 | 0, 565 | 566 | 43, 567 | 0, 568 | 569 | 38, 570 | 43, 571 | 0, 572 | 573 | 30, 574 | 43, 575 | 0, 576 | 577 | 43, 578 | 0, 579 | 580 | 43, 581 | 0, 582 | 583 | 42, 584 | 43, 585 | 0, 586 | 587 | 43, 588 | 0, 589 | 590 | 32, 591 | 43, 592 | 0, 593 | 594 | 43, 595 | 0, 596 | 597 | 43, 598 | 0, 599 | 600 | 43, 601 | 0, 602 | 603 | 50, 604 | 0, 605 | 606 | 52, 607 | 0, 608 | 609 | 57, 610 | 0, 611 | 612 | 56, 613 | 0, 614 | 615 | 66, 616 | 0, 617 | 618 | 65, 619 | 0, 620 | 621 | 64, 622 | 0, 623 | 624 | 63, 625 | 0, 626 | 627 | 60, 628 | 0, 629 | 630 | 43, 631 | 0, 632 | 633 | 43, 634 | 0, 635 | 636 | 43, 637 | 0, 638 | 639 | 33, 640 | 43, 641 | 0, 642 | 643 | 26, 644 | 43, 645 | 0, 646 | 647 | 43, 648 | 0, 649 | 650 | 29, 651 | 43, 652 | 0, 653 | 654 | 31, 655 | 43, 656 | 0, 657 | 658 | 43, 659 | 0, 660 | 661 | 43, 662 | 0, 663 | 664 | 35, 665 | 43, 666 | 0, 667 | 668 | 43, 669 | 0, 670 | 671 | 67, 672 | 0, 673 | 674 | 43, 675 | 0, 676 | 677 | 43, 678 | 0, 679 | 680 | 40, 681 | 43, 682 | 0, 683 | 684 | 43, 685 | 0, 686 | 687 | 39, 688 | 43, 689 | 0, 690 | 691 | 36, 692 | 43, 693 | 0, 694 | 695 | 43, 696 | 0, 697 | 698 | 37, 699 | 43, 700 | 0, 701 | 702 | 28, 703 | 43, 704 | 0, 705 | 706 | 43, 707 | 0, 708 | 709 | 27, 710 | 43, 711 | 0, 712 | 713 | 43, 714 | 0, 715 | 716 | 68, 717 | 0, 718 | 719 | 43, 720 | 0, 721 | 722 | 34, 723 | 43, 724 | 0, 725 | 0}; 726 | # define YYTYPE unsigned char 727 | struct yywork { YYTYPE verify, advance; } yycrank[] = { 728 | 0,0, 0,0, 1,9, 0,0, 729 | 0,0, 0,0, 0,0, 0,0, 730 | 0,0, 0,0, 1,10, 1,11, 731 | 0,0, 10,59, 10,59, 56,95, 732 | 56,95, 0,0, 0,0, 0,0, 733 | 0,0, 0,0, 0,0, 0,0, 734 | 0,0, 0,0, 0,0, 0,0, 735 | 0,0, 0,0, 0,0, 0,0, 736 | 0,0, 0,0, 0,0, 1,12, 737 | 10,59, 6,53, 56,95, 1,13, 738 | 0,0, 1,14, 1,15, 1,16, 739 | 1,17, 1,18, 1,19, 1,20, 740 | 1,21, 1,22, 4,49, 14,60, 741 | 4,50, 16,61, 49,85, 50,86, 742 | 0,0, 0,0, 0,0, 1,23, 743 | 1,24, 1,25, 1,26, 1,27, 744 | 23,63, 1,9, 1,28, 22,62, 745 | 22,62, 22,62, 22,62, 22,62, 746 | 22,62, 22,62, 22,62, 22,62, 747 | 22,62, 25,64, 25,65, 27,66, 748 | 0,0, 7,55, 0,0, 0,0, 749 | 0,0, 0,0, 0,0, 0,0, 750 | 0,0, 7,56, 7,57, 0,0, 751 | 1,29, 8,58, 1,30, 6,54, 752 | 1,9, 90,108, 1,31, 1,32, 753 | 1,28, 1,33, 1,34, 1,35, 754 | 1,28, 1,36, 1,37, 1,28, 755 | 1,28, 1,38, 1,28, 1,39, 756 | 1,40, 1,28, 1,28, 1,28, 757 | 1,28, 1,41, 1,28, 1,42, 758 | 1,43, 1,28, 1,28, 1,28, 759 | 1,44, 1,45, 1,46, 2,12, 760 | 7,55, 31,68, 32,69, 2,13, 761 | 33,70, 2,14, 2,15, 2,16, 762 | 2,17, 2,18, 2,19, 2,20, 763 | 2,21, 34,71, 35,73, 34,72, 764 | 7,55, 7,55, 38,77, 39,78, 765 | 35,74, 37,75, 40,79, 2,23, 766 | 2,24, 2,25, 2,26, 2,27, 767 | 41,80, 37,76, 42,83, 43,84, 768 | 68,96, 69,97, 71,98, 41,81, 769 | 72,99, 73,100, 74,101, 77,102, 770 | 78,103, 80,104, 82,105, 83,106, 771 | 7,58, 41,82, 84,107, 7,55, 772 | 96,110, 7,55, 97,111, 98,112, 773 | 3,47, 101,113, 104,114, 105,115, 774 | 2,29, 107,116, 2,30, 110,118, 775 | 3,47, 3,48, 111,119, 2,32, 776 | 2,28, 2,33, 2,34, 2,35, 777 | 2,28, 2,36, 2,37, 2,28, 778 | 2,28, 2,38, 2,28, 2,39, 779 | 2,40, 2,28, 2,28, 2,28, 780 | 2,28, 2,41, 2,28, 2,42, 781 | 2,43, 2,28, 2,28, 2,28, 782 | 2,44, 2,45, 2,46, 3,49, 783 | 5,51, 3,50, 113,120, 116,121, 784 | 117,122, 120,123, 123,125, 3,47, 785 | 5,51, 5,52, 108,117, 108,117, 786 | 108,117, 108,117, 108,117, 108,117, 787 | 108,117, 108,117, 108,117, 108,117, 788 | 125,126, 0,0, 0,0, 3,47, 789 | 3,47, 0,0, 0,0, 0,0, 790 | 0,0, 0,0, 0,0, 0,0, 791 | 0,0, 5,53, 122,124, 122,124, 792 | 122,124, 122,124, 122,124, 122,124, 793 | 122,124, 122,124, 122,124, 122,124, 794 | 0,0, 0,0, 0,0, 5,51, 795 | 0,0, 0,0, 0,0, 0,0, 796 | 0,0, 0,0, 3,47, 0,0, 797 | 3,47, 0,0, 0,0, 0,0, 798 | 0,0, 0,0, 0,0, 5,51, 799 | 5,51, 0,0, 0,0, 0,0, 800 | 0,0, 0,0, 0,0, 0,0, 801 | 0,0, 0,0, 0,0, 0,0, 802 | 0,0, 0,0, 0,0, 0,0, 803 | 28,67, 28,67, 28,67, 28,67, 804 | 28,67, 28,67, 28,67, 28,67, 805 | 28,67, 28,67, 0,0, 5,54, 806 | 0,0, 0,0, 5,51, 0,0, 807 | 5,51, 28,67, 28,67, 28,67, 808 | 28,67, 28,67, 28,67, 28,67, 809 | 28,67, 28,67, 28,67, 28,67, 810 | 28,67, 28,67, 28,67, 28,67, 811 | 28,67, 28,67, 28,67, 28,67, 812 | 28,67, 28,67, 28,67, 28,67, 813 | 28,67, 28,67, 28,67, 0,0, 814 | 0,0, 0,0, 0,0, 28,67, 815 | 0,0, 28,67, 28,67, 28,67, 816 | 28,67, 28,67, 28,67, 28,67, 817 | 28,67, 28,67, 28,67, 28,67, 818 | 28,67, 28,67, 28,67, 28,67, 819 | 28,67, 28,67, 28,67, 28,67, 820 | 28,67, 28,67, 28,67, 28,67, 821 | 28,67, 28,67, 28,67, 54,87, 822 | 54,88, 0,0, 0,0, 0,0, 823 | 0,0, 0,0, 0,0, 0,0, 824 | 0,0, 0,0, 0,0, 0,0, 825 | 0,0, 0,0, 0,0, 0,0, 826 | 0,0, 0,0, 0,0, 0,0, 827 | 0,0, 0,0, 54,87, 0,0, 828 | 54,89, 0,0, 0,0, 0,0, 829 | 0,0, 0,0, 0,0, 0,0, 830 | 0,0, 0,0, 0,0, 0,0, 831 | 0,0, 0,0, 54,90, 54,90, 832 | 54,90, 54,90, 54,90, 54,90, 833 | 54,90, 54,90, 54,90, 54,90, 834 | 92,109, 92,109, 92,109, 92,109, 835 | 92,109, 92,109, 92,109, 92,109, 836 | 92,109, 92,109, 92,109, 92,109, 837 | 92,109, 92,109, 92,109, 92,109, 838 | 92,109, 92,109, 92,109, 92,109, 839 | 92,109, 92,109, 92,109, 92,109, 840 | 92,109, 92,109, 92,109, 92,109, 841 | 92,109, 92,109, 92,109, 92,109, 842 | 0,0, 0,0, 54,91, 0,0, 843 | 54,92, 0,0, 0,0, 0,0, 844 | 0,0, 0,0, 0,0, 0,0, 845 | 0,0, 0,0, 0,0, 0,0, 846 | 0,0, 0,0, 0,0, 0,0, 847 | 54,93, 0,0, 0,0, 0,0, 848 | 0,0, 0,0, 54,94, 0,0, 849 | 0,0}; 850 | struct yysvf yysvec[] = { 851 | 0, 0, 0, 852 | yycrank+-1, 0, yyvstop+1, 853 | yycrank+-93, yysvec+1, yyvstop+4, 854 | yycrank+-179, 0, yyvstop+7, 855 | yycrank+-10, yysvec+3, yyvstop+10, 856 | yycrank+-219, 0, yyvstop+13, 857 | yycrank+-3, yysvec+5, yyvstop+16, 858 | yycrank+-80, 0, yyvstop+19, 859 | yycrank+-1, yysvec+7, yyvstop+22, 860 | yycrank+0, 0, yyvstop+25, 861 | yycrank+4, 0, yyvstop+27, 862 | yycrank+0, yysvec+10, yyvstop+30, 863 | yycrank+0, 0, yyvstop+33, 864 | yycrank+0, 0, yyvstop+36, 865 | yycrank+9, 0, yyvstop+39, 866 | yycrank+0, 0, yyvstop+42, 867 | yycrank+12, 0, yyvstop+45, 868 | yycrank+0, 0, yyvstop+48, 869 | yycrank+0, 0, yyvstop+51, 870 | yycrank+0, 0, yyvstop+54, 871 | yycrank+0, 0, yyvstop+57, 872 | yycrank+0, 0, yyvstop+60, 873 | yycrank+19, 0, yyvstop+63, 874 | yycrank+3, 0, yyvstop+66, 875 | yycrank+0, 0, yyvstop+69, 876 | yycrank+16, 0, yyvstop+72, 877 | yycrank+0, 0, yyvstop+75, 878 | yycrank+18, 0, yyvstop+78, 879 | yycrank+252, 0, yyvstop+81, 880 | yycrank+0, 0, yyvstop+84, 881 | yycrank+0, 0, yyvstop+87, 882 | yycrank+15, yysvec+28, yyvstop+90, 883 | yycrank+16, yysvec+28, yyvstop+93, 884 | yycrank+21, yysvec+28, yyvstop+96, 885 | yycrank+33, yysvec+28, yyvstop+99, 886 | yycrank+31, yysvec+28, yyvstop+102, 887 | yycrank+0, yysvec+28, yyvstop+105, 888 | yycrank+47, yysvec+28, yyvstop+109, 889 | yycrank+45, yysvec+28, yyvstop+112, 890 | yycrank+42, yysvec+28, yyvstop+115, 891 | yycrank+48, yysvec+28, yyvstop+118, 892 | yycrank+52, yysvec+28, yyvstop+121, 893 | yycrank+61, yysvec+28, yyvstop+124, 894 | yycrank+55, yysvec+28, yyvstop+127, 895 | yycrank+0, 0, yyvstop+130, 896 | yycrank+0, 0, yyvstop+133, 897 | yycrank+0, 0, yyvstop+136, 898 | yycrank+0, 0, yyvstop+139, 899 | yycrank+0, 0, yyvstop+141, 900 | yycrank+12, 0, yyvstop+143, 901 | yycrank+14, 0, yyvstop+145, 902 | yycrank+0, 0, yyvstop+147, 903 | yycrank+0, 0, yyvstop+149, 904 | yycrank+0, 0, yyvstop+151, 905 | yycrank+366, 0, yyvstop+154, 906 | yycrank+0, 0, yyvstop+157, 907 | yycrank+6, 0, yyvstop+159, 908 | yycrank+0, yysvec+56, yyvstop+162, 909 | yycrank+0, 0, yyvstop+165, 910 | yycrank+0, yysvec+10, yyvstop+168, 911 | yycrank+0, 0, yyvstop+170, 912 | yycrank+0, 0, yyvstop+172, 913 | yycrank+0, yysvec+22, yyvstop+174, 914 | yycrank+0, 0, yyvstop+176, 915 | yycrank+0, 0, yyvstop+178, 916 | yycrank+0, 0, yyvstop+180, 917 | yycrank+0, 0, yyvstop+182, 918 | yycrank+0, yysvec+28, yyvstop+184, 919 | yycrank+46, yysvec+28, yyvstop+186, 920 | yycrank+60, yysvec+28, yyvstop+188, 921 | yycrank+0, yysvec+28, yyvstop+190, 922 | yycrank+47, yysvec+28, yyvstop+193, 923 | yycrank+64, yysvec+28, yyvstop+195, 924 | yycrank+51, yysvec+28, yyvstop+197, 925 | yycrank+56, yysvec+28, yyvstop+199, 926 | yycrank+0, yysvec+28, yyvstop+201, 927 | yycrank+0, yysvec+28, yyvstop+204, 928 | yycrank+51, yysvec+28, yyvstop+207, 929 | yycrank+60, yysvec+28, yyvstop+209, 930 | yycrank+0, yysvec+28, yyvstop+211, 931 | yycrank+68, yysvec+28, yyvstop+214, 932 | yycrank+0, yysvec+28, yyvstop+216, 933 | yycrank+58, yysvec+28, yyvstop+219, 934 | yycrank+57, yysvec+28, yyvstop+221, 935 | yycrank+69, yysvec+28, yyvstop+223, 936 | yycrank+0, 0, yyvstop+225, 937 | yycrank+0, 0, yyvstop+227, 938 | yycrank+0, 0, yyvstop+229, 939 | yycrank+0, 0, yyvstop+231, 940 | yycrank+0, 0, yyvstop+233, 941 | yycrank+5, 0, 0, 942 | yycrank+0, 0, yyvstop+235, 943 | yycrank+360, 0, 0, 944 | yycrank+0, 0, yyvstop+237, 945 | yycrank+0, 0, yyvstop+239, 946 | yycrank+0, yysvec+56, yyvstop+241, 947 | yycrank+79, yysvec+28, yyvstop+243, 948 | yycrank+81, yysvec+28, yyvstop+245, 949 | yycrank+78, yysvec+28, yyvstop+247, 950 | yycrank+0, yysvec+28, yyvstop+249, 951 | yycrank+0, yysvec+28, yyvstop+252, 952 | yycrank+82, yysvec+28, yyvstop+255, 953 | yycrank+0, yysvec+28, yyvstop+257, 954 | yycrank+0, yysvec+28, yyvstop+260, 955 | yycrank+72, yysvec+28, yyvstop+263, 956 | yycrank+82, yysvec+28, yyvstop+265, 957 | yycrank+0, yysvec+28, yyvstop+267, 958 | yycrank+77, yysvec+28, yyvstop+270, 959 | yycrank+182, 0, 0, 960 | yycrank+0, 0, yyvstop+272, 961 | yycrank+66, yysvec+28, yyvstop+274, 962 | yycrank+83, yysvec+28, yyvstop+276, 963 | yycrank+0, yysvec+28, yyvstop+278, 964 | yycrank+106, yysvec+28, yyvstop+281, 965 | yycrank+0, yysvec+28, yyvstop+283, 966 | yycrank+0, yysvec+28, yyvstop+286, 967 | yycrank+122, yysvec+28, yyvstop+289, 968 | yycrank+132, 0, 0, 969 | yycrank+0, yysvec+28, yyvstop+291, 970 | yycrank+0, yysvec+28, yyvstop+294, 971 | yycrank+120, yysvec+28, yyvstop+297, 972 | yycrank+0, yysvec+28, yyvstop+299, 973 | yycrank+206, 0, 0, 974 | yycrank+115, yysvec+28, yyvstop+302, 975 | yycrank+0, 0, yyvstop+304, 976 | yycrank+130, yysvec+28, yyvstop+306, 977 | yycrank+0, yysvec+28, yyvstop+308, 978 | 0, 0, 0}; 979 | struct yywork *yytop = yycrank+482; 980 | struct yysvf *yybgin = yysvec+1; 981 | unsigned char yymatch[] = { 982 | 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 983 | 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 984 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 985 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 986 | 011 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 987 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 988 | '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , 989 | '0' ,'0' ,01 ,01 ,01 ,01 ,01 ,01 , 990 | '@' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 991 | 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 992 | 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 993 | 'A' ,'A' ,'A' ,'@' ,'@' ,'@' ,'@' ,'_' , 994 | 01 ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 995 | 'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 996 | 'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' ,'a' , 997 | 'a' ,'a' ,'a' ,01 ,01 ,01 ,01 ,01 , 998 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 999 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1000 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1001 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1002 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1003 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1004 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1005 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1006 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1007 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1008 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1009 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1010 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1011 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1012 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1013 | 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 1014 | 0}; 1015 | unsigned char yyextra[] = { 1016 | 0,0,0,0,0,0,0,0, 1017 | 0,0,0,0,0,0,0,0, 1018 | 0,0,0,0,0,0,0,0, 1019 | 0,0,0,0,0,0,0,0, 1020 | 0,0,0,0,0,0,0,0, 1021 | 0,0,0,0,0,0,0,0, 1022 | 0,0,0,0,0,0,0,0, 1023 | 0,0,0,0,0,0,0,0, 1024 | 0,0,0,0,0,0,0,0, 1025 | 0}; 1026 | /* 1027 | * (c) Copyright 1990, OPEN SOFTWARE FOUNDATION, INC. 1028 | * ALL RIGHTS RESERVED 1029 | */ 1030 | /* 1031 | * OSF/1 Release 1.0 1032 | */ 1033 | /* 1034 | # 1035 | # IBM CONFIDENTIAL 1036 | # Copyright International Business Machines Corp. 1989 1037 | # Unpublished Work 1038 | # All Rights Reserved 1039 | # Licensed Material - Property of IBM 1040 | # 1041 | # 1042 | # US Government Users Restricted Rights - Use, duplication or 1043 | # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 1044 | # 1045 | */ 1046 | /* @(#)ncform 1.3 com/lib/l,3.1,8951 9/7/89 18:48:47 */ 1047 | int yylineno =1; 1048 | # define YYU(x) x 1049 | unsigned char yytext[YYLMAX]; 1050 | struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; 1051 | unsigned char yysbuf[YYLMAX]; 1052 | unsigned char *yysptr = yysbuf; 1053 | int *yyfnd; 1054 | extern struct yysvf *yyestate; 1055 | int yyprevious = 10; 1056 | yylook(){ 1057 | register struct yysvf *yystate, **lsp; 1058 | register struct yywork *yyt; 1059 | struct yysvf *yyz; 1060 | int yych, yyfirst; 1061 | struct yywork *yyr; 1062 | # ifdef LEXDEBUG 1063 | int debug; 1064 | # endif 1065 | unsigned char *yylastch; 1066 | /* start off machines */ 1067 | # ifdef LEXDEBUG 1068 | debug = 0; 1069 | # endif 1070 | yyfirst=1; 1071 | if (!yymorfg) 1072 | yylastch = yytext; 1073 | else { 1074 | yymorfg=0; 1075 | yylastch = yytext+yyleng; 1076 | } 1077 | for(;;){ 1078 | lsp = yylstate; 1079 | yyestate = yystate = yybgin; 1080 | if (yyprevious==10) yystate++; 1081 | for (;;){ 1082 | # ifdef LEXDEBUG 1083 | if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); 1084 | # endif 1085 | yyt = yystate->yystoff; 1086 | if(yyt == yycrank && !yyfirst){ /* may not be any transitions */ 1087 | yyz = yystate->yyother; 1088 | if(yyz == 0)break; 1089 | if(yyz->yystoff == yycrank)break; 1090 | } 1091 | *yylastch++ = yych = input(); 1092 | yyfirst=0; 1093 | tryagain: 1094 | # ifdef LEXDEBUG 1095 | if(debug){ 1096 | fprintf(yyout,"char "); 1097 | allprint(yych); 1098 | putchar('\n'); 1099 | } 1100 | # endif 1101 | yyr = yyt; 1102 | if ( yyt > yycrank){ 1103 | yyt = yyr + yych; 1104 | if (yyt <= yytop && yyt->verify+yysvec == yystate){ 1105 | if(yyt->advance+yysvec == YYLERR) /* error transitions */ 1106 | {unput(*--yylastch);break;} 1107 | *lsp++ = yystate = yyt->advance+yysvec; 1108 | goto contin; 1109 | } 1110 | } 1111 | # ifdef YYOPTIM 1112 | else if(yyt < yycrank) { /* r < yycrank */ 1113 | yyt = yyr = yycrank+(yycrank-yyt); 1114 | # ifdef LEXDEBUG 1115 | if(debug)fprintf(yyout,"compressed state\n"); 1116 | # endif 1117 | yyt = yyt + yych; 1118 | if(yyt <= yytop && yyt->verify+yysvec == yystate){ 1119 | if(yyt->advance+yysvec == YYLERR) /* error transitions */ 1120 | {unput(*--yylastch);break;} 1121 | *lsp++ = yystate = yyt->advance+yysvec; 1122 | goto contin; 1123 | } 1124 | yyt = yyr + YYU(yymatch[yych]); 1125 | # ifdef LEXDEBUG 1126 | if(debug){ 1127 | fprintf(yyout,"try fall back character "); 1128 | allprint(YYU(yymatch[yych])); 1129 | putchar('\n'); 1130 | } 1131 | # endif 1132 | if(yyt <= yytop && yyt->verify+yysvec == yystate){ 1133 | if(yyt->advance+yysvec == YYLERR) /* error transition */ 1134 | {unput(*--yylastch);break;} 1135 | *lsp++ = yystate = yyt->advance+yysvec; 1136 | goto contin; 1137 | } 1138 | } 1139 | if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ 1140 | # ifdef LEXDEBUG 1141 | if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); 1142 | # endif 1143 | goto tryagain; 1144 | } 1145 | # endif 1146 | else 1147 | {unput(*--yylastch);break;} 1148 | contin: 1149 | # ifdef LEXDEBUG 1150 | if(debug){ 1151 | fprintf(yyout,"state %d char ",yystate-yysvec-1); 1152 | allprint(yych); 1153 | putchar('\n'); 1154 | } 1155 | # endif 1156 | ; 1157 | } 1158 | # ifdef LEXDEBUG 1159 | if(debug){ 1160 | fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); 1161 | allprint(yych); 1162 | putchar('\n'); 1163 | } 1164 | # endif 1165 | while (lsp-- > yylstate){ 1166 | *yylastch-- = 0; 1167 | if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ 1168 | yyolsp = lsp; 1169 | if(yyextra[*yyfnd]){ /* must backup */ 1170 | while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ 1171 | lsp--; 1172 | unput(*yylastch--); 1173 | } 1174 | } 1175 | yyprevious = YYU(*yylastch); 1176 | yylsp = lsp; 1177 | yyleng = yylastch-yytext+1; 1178 | yytext[yyleng] = 0; 1179 | # ifdef LEXDEBUG 1180 | if(debug){ 1181 | fprintf(yyout,"\nmatch "); 1182 | sprint(yytext); 1183 | fprintf(yyout," action %d\n",*yyfnd); 1184 | } 1185 | # endif 1186 | return(*yyfnd++); 1187 | } 1188 | unput(*yylastch); 1189 | } 1190 | if (yytext[0] == 0 /* && feof(yyin) */) 1191 | { 1192 | yysptr=yysbuf; 1193 | return(0); 1194 | } 1195 | yyprevious = yytext[0] = input(); 1196 | if (yyprevious>0) 1197 | output(yyprevious); 1198 | yylastch=yytext; 1199 | # ifdef LEXDEBUG 1200 | if(debug)putchar('\n'); 1201 | # endif 1202 | } 1203 | } 1204 | yyback(p, m) 1205 | int *p; 1206 | { 1207 | if (p==0) return(0); 1208 | while (*p) 1209 | { 1210 | if (*p++ == m) 1211 | return(1); 1212 | } 1213 | return(0); 1214 | } 1215 | /* the following are only used in the lex library */ 1216 | yyinput(){ 1217 | return(input()); 1218 | } 1219 | yyoutput(c) 1220 | int c; { 1221 | output(c); 1222 | } 1223 | yyunput(c) 1224 | int c; { 1225 | unput(c); 1226 | } 1227 | -------------------------------------------------------------------------------- /chap4/makefile: -------------------------------------------------------------------------------- 1 | a.out: parsetest.o y.tab.o lex.yy.o errormsg.o util.o 2 | cc -g parsetest.o y.tab.o lex.yy.o errormsg.o util.o 3 | 4 | parsetest.o: parsetest.c errormsg.h util.h 5 | cc -g -c parsetest.c 6 | 7 | y.tab.o: y.tab.c 8 | cc -g -c y.tab.c 9 | 10 | y.tab.c: tiger.grm 11 | yacc -dv tiger.grm 12 | 13 | y.tab.h: y.tab.c 14 | echo "y.tab.h was created at the same time as y.tab.c" 15 | 16 | errormsg.o: errormsg.c errormsg.h util.h 17 | cc -g -c errormsg.c 18 | 19 | lex.yy.o: lex.yy.c y.tab.h errormsg.h util.h 20 | cc -g -c lex.yy.c 21 | 22 | #lex.yy.c: tiger.lex 23 | # lex tiger.lex 24 | 25 | util.o: util.c util.h 26 | cc -g -c util.c 27 | 28 | clean: 29 | rm -f a.out util.o parsetest.o lex.yy.o errormsg.o y.tab.c y.tab.h y.tab.o 30 | -------------------------------------------------------------------------------- /chap4/parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * parse.c - Parse source file. 3 | */ 4 | 5 | #include 6 | #include "util.h" 7 | #include "symbol.h" 8 | #include "absyn.h" 9 | #include "errormsg.h" 10 | #include "parse.h" 11 | 12 | extern int yyparse(void); 13 | extern A_exp absyn_root; 14 | 15 | /* parse source file fname; 16 | return abstract syntax data structure */ 17 | A_exp parse(string fname) 18 | {EM_reset(fname); 19 | if (yyparse() == 0) /* parsing worked */ 20 | return absyn_root; 21 | else return NULL; 22 | } 23 | -------------------------------------------------------------------------------- /chap4/parse.h: -------------------------------------------------------------------------------- 1 | /* function prototype from parse.c */ 2 | A_exp parse(string fname); 3 | 4 | -------------------------------------------------------------------------------- /chap4/prabsyn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * prabsyn.c - Print Abstract Syntax data structures. Most functions 3 | * handle an instance of an abstract syntax rule. 4 | */ 5 | 6 | #include 7 | #include "util.h" 8 | #include "symbol.h" /* symbol table data structures */ 9 | #include "absyn.h" /* abstract syntax data structures */ 10 | #include "prabsyn.h" /* function prototype */ 11 | 12 | /* local function prototypes */ 13 | static void pr_var(FILE *out, A_var v, int d); 14 | static void pr_dec(FILE *out, A_dec v, int d); 15 | static void pr_ty(FILE *out, A_ty v, int d); 16 | static void pr_field(FILE *out, A_field v, int d); 17 | static void pr_fieldList(FILE *out, A_fieldList v, int d); 18 | static void pr_expList(FILE *out, A_expList v, int d); 19 | static void pr_fundec(FILE *out, A_fundec v, int d); 20 | static void pr_fundecList(FILE *out, A_fundecList v, int d); 21 | static void pr_decList(FILE *out, A_decList v, int d); 22 | static void pr_namety(FILE *out, A_namety v, int d); 23 | static void pr_nametyList(FILE *out, A_nametyList v, int d); 24 | static void pr_efield(FILE *out, A_efield v, int d); 25 | static void pr_efieldList(FILE *out, A_efieldList v, int d); 26 | 27 | static void indent(FILE *out, int d) { 28 | int i; 29 | for (i = 0; i <= d; i++) fprintf(out, " "); 30 | } 31 | 32 | /* Print A_var types. Indent d spaces. */ 33 | static void pr_var(FILE *out, A_var v, int d) { 34 | indent(out, d); 35 | switch (v->kind) { 36 | case A_simpleVar: 37 | fprintf(out, "simpleVar(%s)", S_name(v->u.simple)); 38 | break; 39 | case A_fieldVar: 40 | fprintf(out, "%s\n", "fieldVar("); 41 | pr_var(out, v->u.field.var, d+1); fprintf(out, "%s\n", ","); 42 | indent(out, d+1); fprintf(out, "%s)", S_name(v->u.field.sym)); 43 | break; 44 | case A_subscriptVar: 45 | fprintf(out, "%s\n", "subscriptVar("); 46 | pr_var(out, v->u.subscript.var, d+1); fprintf(out, "%s\n", ","); 47 | pr_exp(out, v->u.subscript.exp, d+1); fprintf(out, "%s", ")"); 48 | break; 49 | default: 50 | assert(0); 51 | } 52 | } 53 | 54 | static char str_oper[][12] = { 55 | "PLUS", "MINUS", "TIMES", "DIVIDE", 56 | "EQUAL", "NOTEQUAL", "LESSTHAN", "LESSEQ", "GREAT", "GREATEQ"}; 57 | 58 | static void pr_oper(FILE *out, A_oper d) { 59 | fprintf(out, "%s", str_oper[d]); 60 | } 61 | 62 | /* Print A_var types. Indent d spaces. */ 63 | void pr_exp(FILE *out, A_exp v, int d) { 64 | indent(out, d); 65 | switch (v->kind) { 66 | case A_varExp: 67 | fprintf(out, "varExp(\n"); pr_var(out, v->u.var, d+1); 68 | fprintf(out, "%s", ")"); 69 | break; 70 | case A_nilExp: 71 | fprintf(out, "nilExp()"); 72 | break; 73 | case A_intExp: 74 | fprintf(out, "intExp(%d)", v->u.intt); 75 | break; 76 | case A_stringExp: 77 | fprintf(out, "stringExp(%s)", v->u.stringg); 78 | break; 79 | case A_callExp: 80 | fprintf(out, "callExp(%s,\n", S_name(v->u.call.func)); 81 | pr_expList(out, v->u.call.args, d+1); fprintf(out, ")"); 82 | break; 83 | case A_opExp: 84 | fprintf(out, "opExp(\n"); 85 | indent(out, d+1); pr_oper(out, v->u.op.oper); fprintf(out, ",\n"); 86 | pr_exp(out, v->u.op.left, d+1); fprintf(out, ",\n"); 87 | pr_exp(out, v->u.op.right, d+1); fprintf(out, ")"); 88 | break; 89 | case A_recordExp: 90 | fprintf(out, "recordExp(%s,\n", S_name(v->u.record.typ)); 91 | pr_efieldList(out, v->u.record.fields, d+1); fprintf(out, ")"); 92 | break; 93 | case A_seqExp: 94 | fprintf(out, "seqExp(\n"); 95 | pr_expList(out, v->u.seq, d+1); fprintf(out, ")"); 96 | break; 97 | case A_assignExp: 98 | fprintf(out, "assignExp(\n"); 99 | pr_var(out, v->u.assign.var, d+1); fprintf(out, ",\n"); 100 | pr_exp(out, v->u.assign.exp, d+1); fprintf(out, ")"); 101 | break; 102 | case A_ifExp: 103 | fprintf(out, "iffExp(\n"); 104 | pr_exp(out, v->u.iff.test, d+1); fprintf(out, ",\n"); 105 | pr_exp(out, v->u.iff.then, d+1); 106 | if (v->u.iff.elsee) { /* else is optional */ 107 | fprintf(out, ",\n"); 108 | pr_exp(out, v->u.iff.elsee, d+1); 109 | } 110 | fprintf(out, ")"); 111 | break; 112 | case A_whileExp: 113 | fprintf(out, "whileExp(\n"); 114 | pr_exp(out, v->u.whilee.test, d+1); fprintf(out, ",\n"); 115 | pr_exp(out, v->u.whilee.body, d+1); fprintf(out, ")\n"); 116 | break; 117 | case A_forExp: 118 | fprintf(out, "forExp(%s,\n", S_name(v->u.forr.var)); 119 | pr_exp(out, v->u.forr.lo, d+1); fprintf(out, ",\n"); 120 | pr_exp(out, v->u.forr.hi, d+1); fprintf(out, "%s\n", ","); 121 | pr_exp(out, v->u.forr.body, d+1); fprintf(out, ",\n"); 122 | indent(out, d+1); fprintf(out, "%s", v->u.forr.escape ? "TRUE)" : "FALSE)"); 123 | break; 124 | case A_breakExp: 125 | fprintf(out, "breakExp()"); 126 | break; 127 | case A_letExp: 128 | fprintf(out, "letExp(\n"); 129 | pr_decList(out, v->u.let.decs, d+1); fprintf(out, ",\n"); 130 | pr_exp(out, v->u.let.body, d+1); fprintf(out, ")"); 131 | break; 132 | case A_arrayExp: 133 | fprintf(out, "arrayExp(%s,\n", S_name(v->u.array.typ)); 134 | pr_exp(out, v->u.array.size, d+1); fprintf(out, ",\n"); 135 | pr_exp(out, v->u.array.init, d+1); fprintf(out, ")"); 136 | break; 137 | default: 138 | assert(0); 139 | } 140 | } 141 | 142 | static void pr_dec(FILE *out, A_dec v, int d) { 143 | indent(out, d); 144 | switch (v->kind) { 145 | case A_functionDec: 146 | fprintf(out, "functionDec(\n"); 147 | pr_fundecList(out, v->u.function, d+1); fprintf(out, ")"); 148 | break; 149 | case A_varDec: 150 | fprintf(out, "varDec(%s,\n", S_name(v->u.var.var)); 151 | if (v->u.var.typ) { 152 | indent(out, d+1); fprintf(out, "%s,\n", S_name(v->u.var.typ)); 153 | } 154 | pr_exp(out, v->u.var.init, d+1); fprintf(out, ",\n"); 155 | indent(out, d+1); fprintf(out, "%s", v->u.var.escape ? "TRUE)" : "FALSE)"); 156 | break; 157 | case A_typeDec: 158 | fprintf(out, "typeDec(\n"); 159 | pr_nametyList(out, v->u.type, d+1); fprintf(out, ")"); 160 | break; 161 | default: 162 | assert(0); 163 | } 164 | } 165 | 166 | static void pr_ty(FILE *out, A_ty v, int d) { 167 | indent(out, d); 168 | switch (v->kind) { 169 | case A_nameTy: 170 | fprintf(out, "nameTy(%s)", S_name(v->u.name)); 171 | break; 172 | case A_recordTy: 173 | fprintf(out, "recordTy(\n"); 174 | pr_fieldList(out, v->u.record, d+1); fprintf(out, ")"); 175 | break; 176 | case A_arrayTy: 177 | fprintf(out, "arrayTy(%s)", S_name(v->u.array)); 178 | break; 179 | default: 180 | assert(0); 181 | } 182 | } 183 | 184 | static void pr_field(FILE *out, A_field v, int d) { 185 | indent(out, d); 186 | fprintf(out, "field(%s,\n", S_name(v->name)); 187 | indent(out, d+1); fprintf(out, "%s,\n", S_name(v->typ)); 188 | indent(out, d+1); fprintf(out, "%s", v->escape ? "TRUE)" : "FALSE)"); 189 | } 190 | 191 | static void pr_fieldList(FILE *out, A_fieldList v, int d) { 192 | indent(out, d); 193 | if (v) { 194 | fprintf(out, "fieldList(\n"); 195 | pr_field(out, v->head, d+1); fprintf(out, ",\n"); 196 | pr_fieldList(out, v->tail, d+1); fprintf(out, ")"); 197 | } 198 | else fprintf(out, "fieldList()"); 199 | } 200 | 201 | static void pr_expList(FILE *out, A_expList v, int d) { 202 | indent(out, d); 203 | if (v) { 204 | fprintf(out, "expList(\n"); 205 | pr_exp(out, v->head, d+1); fprintf(out, ",\n"); 206 | pr_expList(out, v->tail, d+1); 207 | fprintf(out, ")"); 208 | } 209 | else fprintf(out, "expList()"); 210 | 211 | } 212 | 213 | static void pr_fundec(FILE *out, A_fundec v, int d) { 214 | indent(out, d); 215 | fprintf(out, "fundec(%s,\n", S_name(v->name)); 216 | pr_fieldList(out, v->params, d+1); fprintf(out, ",\n"); 217 | if (v->result) { 218 | indent(out, d+1); fprintf(out, "%s,\n", S_name(v->result)); 219 | } 220 | pr_exp(out, v->body, d+1); fprintf(out, ")"); 221 | } 222 | 223 | static void pr_fundecList(FILE *out, A_fundecList v, int d) { 224 | indent(out, d); 225 | if (v) { 226 | fprintf(out, "fundecList(\n"); 227 | pr_fundec(out, v->head, d+1); fprintf(out, ",\n"); 228 | pr_fundecList(out, v->tail, d+1); fprintf(out, ")"); 229 | } 230 | else fprintf(out, "fundecList()"); 231 | } 232 | 233 | static void pr_decList(FILE *out, A_decList v, int d) { 234 | indent(out, d); 235 | if (v) { 236 | fprintf(out, "decList(\n"); 237 | pr_dec(out, v->head, d+1); fprintf(out, ",\n"); 238 | pr_decList(out, v->tail, d+1); 239 | fprintf(out, ")"); 240 | } 241 | else fprintf(out, "decList()"); 242 | 243 | } 244 | 245 | static void pr_namety(FILE *out, A_namety v, int d) { 246 | indent(out, d); 247 | fprintf(out, "namety(%s,\n", S_name(v->name)); 248 | pr_ty(out, v->ty, d+1); fprintf(out, ")"); 249 | } 250 | 251 | static void pr_nametyList(FILE *out, A_nametyList v, int d) { 252 | indent(out, d); 253 | if (v) { 254 | fprintf(out, "nametyList(\n"); 255 | pr_namety(out, v->head, d+1); fprintf(out, ",\n"); 256 | pr_nametyList(out, v->tail, d+1); fprintf(out, ")"); 257 | } 258 | else fprintf(out, "nametyList()"); 259 | } 260 | 261 | static void pr_efield(FILE *out, A_efield v, int d) { 262 | indent(out, d); 263 | if (v) { 264 | fprintf(out, "efield(%s,\n", S_name(v->name)); 265 | pr_exp(out, v->exp, d+1); fprintf(out, ")"); 266 | } 267 | else fprintf(out, "efield()"); 268 | } 269 | 270 | static void pr_efieldList(FILE *out, A_efieldList v, int d) { 271 | indent(out, d); 272 | if (v) { 273 | fprintf(out, "efieldList(\n"); 274 | pr_efield(out, v->head, d+1); fprintf(out, ",\n"); 275 | pr_efieldList(out, v->tail, d+1); fprintf(out, ")"); 276 | } 277 | else fprintf(out, "efieldList()"); 278 | } 279 | 280 | 281 | 282 | 283 | -------------------------------------------------------------------------------- /chap4/prabsyn.h: -------------------------------------------------------------------------------- 1 | /* function prototype from prabsyn.c */ 2 | void pr_exp(FILE *out, A_exp v, int d); 3 | 4 | -------------------------------------------------------------------------------- /chap4/symbol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "util.h" 4 | #include "symbol.h" 5 | #include "table.h" 6 | 7 | struct S_symbol_ {string name; S_symbol next;}; 8 | 9 | static S_symbol mksymbol(string name, S_symbol next) 10 | {S_symbol s=checked_malloc(sizeof(*s)); 11 | s->name=name; s->next=next; 12 | return s; 13 | } 14 | 15 | #define SIZE 109 /* should be prime */ 16 | 17 | static S_symbol hashtable[SIZE]; 18 | 19 | static unsigned int hash(char *s0) 20 | {unsigned int h=0; char *s; 21 | for(s=s0; *s; s++) 22 | h = h*65599 + *s; 23 | return h; 24 | } 25 | 26 | static int streq(string a, string b) 27 | { 28 | return !strcmp(a,b); 29 | } 30 | 31 | S_symbol S_Symbol(string name) 32 | {int index= hash(name) % SIZE; 33 | S_symbol syms = hashtable[index], sym; 34 | for(sym=syms; sym; sym=sym->next) 35 | if (streq(sym->name,name)) return sym; 36 | sym = mksymbol(name,syms); 37 | hashtable[index]=sym; 38 | return sym; 39 | } 40 | 41 | string S_name(S_symbol sym) 42 | { 43 | return sym->name; 44 | } 45 | 46 | S_table S_empty(void) 47 | { 48 | return TAB_empty(); 49 | } 50 | 51 | void S_enter(S_table t, S_symbol sym, void *value) { 52 | TAB_enter(t,sym,value); 53 | } 54 | 55 | void *S_look(S_table t, S_symbol sym) { 56 | return TAB_look(t,sym); 57 | } 58 | 59 | static struct S_symbol_ marksym = {"",0}; 60 | 61 | void S_beginScope(S_table t) 62 | { S_enter(t,&marksym,NULL); 63 | } 64 | 65 | void S_endScope(S_table t) 66 | {S_symbol s; 67 | do s=TAB_pop(t); 68 | while (s != &marksym); 69 | } 70 | 71 | void S_dump(S_table t, void (*show)(S_symbol sym, void *binding)) { 72 | TAB_dump(t, (void (*)(void *, void *)) show); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /chap4/symbol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * symbol.h - Symbols and symbol-tables 3 | * 4 | */ 5 | 6 | typedef struct S_symbol_ *S_symbol; 7 | 8 | /* Make a unique symbol from a given string. 9 | * Different calls to S_Symbol("foo") will yield the same S_symbol 10 | * value, even if the "foo" strings are at different locations. */ 11 | S_symbol S_Symbol(string); 12 | 13 | /* Extract the underlying string from a symbol */ 14 | string S_name(S_symbol); 15 | 16 | /* S_table is a mapping from S_symbol->any, where "any" is represented 17 | * here by void* */ 18 | typedef struct TAB_table_ *S_table; 19 | 20 | /* Make a new table */ 21 | S_table S_empty(void); 22 | 23 | /* Enter a binding "sym->value" into "t", shadowing but not deleting 24 | * any previous binding of "sym". */ 25 | void S_enter(S_table t, S_symbol sym, void *value); 26 | 27 | /* Look up the most recent binding of "sym" in "t", or return NULL 28 | * if sym is unbound. */ 29 | void *S_look(S_table t, S_symbol sym); 30 | 31 | /* Start a new "scope" in "t". Scopes are nested. */ 32 | void S_beginScope(S_table t); 33 | 34 | /* Remove any bindings entered since the current scope began, 35 | and end the current scope. */ 36 | void S_endScope(S_table t); 37 | 38 | -------------------------------------------------------------------------------- /chap4/table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * table.c - Functions to manipulate generic tables. 3 | * Copyright (c) 1997 Andrew W. Appel. 4 | */ 5 | 6 | #include 7 | #include "util.h" 8 | #include "table.h" 9 | 10 | #define TABSIZE 127 11 | 12 | typedef struct binder_ *binder; 13 | struct binder_ {void *key; void *value; binder next; void *prevtop;}; 14 | struct TAB_table_ { 15 | binder table[TABSIZE]; 16 | void *top; 17 | }; 18 | 19 | 20 | static binder Binder(void *key, void *value, binder next, void *prevtop) 21 | {binder b = checked_malloc(sizeof(*b)); 22 | b->key = key; b->value=value; b->next=next; b->prevtop = prevtop; 23 | return b; 24 | } 25 | 26 | TAB_table TAB_empty(void) 27 | { 28 | TAB_table t = checked_malloc(sizeof(*t)); 29 | int i; 30 | t->top = NULL; 31 | for (i = 0; i < TABSIZE; i++) 32 | t->table[i] = NULL; 33 | return t; 34 | } 35 | 36 | /* The cast from pointer to integer in the expression 37 | * ((unsigned)key) % TABSIZE 38 | * may lead to a warning message. However, the code is safe, 39 | * and will still operate correctly. This line is just hashing 40 | * a pointer value into an integer value, and no matter how the 41 | * conversion is done, as long as it is done consistently, a 42 | * reasonable and repeatable index into the table will result. 43 | */ 44 | 45 | void TAB_enter(TAB_table t, void *key, void *value) 46 | {int index; 47 | assert(t && key); 48 | index = ((unsigned)key) % TABSIZE; 49 | t->table[index] = Binder(key, value,t->table[index], t->top); 50 | t->top = key; 51 | } 52 | 53 | void *TAB_look(TAB_table t, void *key) 54 | {int index; 55 | binder b; 56 | assert(t && key); 57 | index=((unsigned)key) % TABSIZE; 58 | for(b=t->table[index]; b; b=b->next) 59 | if (b->key==key) return b->value; 60 | return NULL; 61 | } 62 | 63 | void *TAB_pop(TAB_table t) { 64 | void *k; binder b; int index; 65 | assert (t); 66 | k = t->top; 67 | assert (k); 68 | index = ((unsigned)k) % TABSIZE; 69 | b = t->table[index]; 70 | assert(b); 71 | t->table[index] = b->next; 72 | t->top=b->prevtop; 73 | return b->key; 74 | } 75 | 76 | void TAB_dump(TAB_table t, void (*show)(void *key, void *value)) { 77 | void *k = t->top; 78 | int index = ((unsigned)k) % TABSIZE; 79 | binder b = t->table[index]; 80 | if (b==NULL) return; 81 | t->table[index]=b->next; 82 | t->top=b->prevtop; 83 | show(b->key,b->value); 84 | TAB_dump(t,show); 85 | assert(t->top == b->prevtop && t->table[index]==b->next); 86 | t->top=k; 87 | t->table[index]=b; 88 | } 89 | -------------------------------------------------------------------------------- /chap4/table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * table.h - generic hash table 3 | * 4 | * No algorithm should use these functions directly, because 5 | * programming with void* is too error-prone. Instead, 6 | * each module should make "wrapper" functions that take 7 | * well-typed arguments and call the TAB_ functions. 8 | */ 9 | 10 | typedef struct TAB_table_ *TAB_table; 11 | 12 | /* Make a new table mapping "keys" to "values". */ 13 | TAB_table TAB_empty(void); 14 | 15 | /* Enter the mapping "key"->"value" into table "t", 16 | * shadowing but not destroying any previous binding for "key". */ 17 | void TAB_enter(TAB_table t, void *key, void *value); 18 | 19 | /* Look up the most recent binding for "key" in table "t" */ 20 | void *TAB_look(TAB_table t, void *key); 21 | 22 | /* Pop the most recent binding and return its key. 23 | * This may expose another binding for the same key, if there was one. */ 24 | void *TAB_pop(TAB_table t); 25 | 26 | 27 | /* Call "show" on every "key"->"value" pair in the table, 28 | * including shadowed bindings, in order from the most 29 | * recent binding of any key to the oldest binding in the table */ 30 | void TAB_dump(TAB_table t, void (*show)(void *key, void *value)); 31 | 32 | 33 | -------------------------------------------------------------------------------- /chap4/tiger.grm: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include "util.h" 4 | #include "symbol.h" 5 | #include "errormsg.h" 6 | #include "absyn.h" 7 | 8 | int yylex(void); /* function prototype */ 9 | 10 | A_exp absyn_root; 11 | 12 | void yyerror(char *s) 13 | { 14 | EM_error(EM_tokPos, "%s", s); 15 | } 16 | %} 17 | 18 | 19 | %union { 20 | int pos; 21 | int ival; 22 | string sval; 23 | A_var var; 24 | A_exp exp; 25 | /* et cetera */ 26 | } 27 | 28 | %token ID STRING 29 | %token INT 30 | 31 | %token 32 | COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK 33 | LBRACE RBRACE DOT 34 | PLUS MINUS TIMES DIVIDE EQ NEQ LT LE GT GE 35 | AND OR ASSIGN 36 | ARRAY IF THEN ELSE WHILE FOR TO DO LET IN END OF 37 | BREAK NIL 38 | FUNCTION VAR TYPE 39 | 40 | %type exp program 41 | /* et cetera */ 42 | 43 | %start program 44 | 45 | %% 46 | 47 | program: exp {absyn_root=$1;} 48 | 49 | exp: ID {$$=A_VarExp(EM_tokPos,A_SimpleVar(EM_tokPos,S_Symbol($1)));} 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /chap5/types.c: -------------------------------------------------------------------------------- 1 | /* 2 | * types.c - 3 | * 4 | * All types and functions declared in this header file begin with "Ty_" 5 | * Linked list types end with "..list" 6 | */ 7 | 8 | #include 9 | #include "util.h" 10 | #include "symbol.h" 11 | #include "types.h" 12 | 13 | static struct Ty_ty_ tynil = {Ty_nil}; 14 | Ty_ty Ty_Nil(void) {return &tynil;} 15 | 16 | static struct Ty_ty_ tyint = {Ty_int}; 17 | Ty_ty Ty_Int(void) {return &tyint;} 18 | 19 | static struct Ty_ty_ tystring = {Ty_string}; 20 | Ty_ty Ty_String(void) {return &tystring;} 21 | 22 | static struct Ty_ty_ tyvoid = {Ty_void}; 23 | Ty_ty Ty_Void(void) {return &tyvoid;} 24 | 25 | Ty_ty Ty_Record(Ty_fieldList fields) 26 | {Ty_ty p = checked_malloc(sizeof(*p)); 27 | p->kind=Ty_record; 28 | p->u.record=fields; 29 | return p; 30 | } 31 | 32 | Ty_ty Ty_Array(Ty_ty ty) 33 | {Ty_ty p = checked_malloc(sizeof(*p)); 34 | p->kind=Ty_array; 35 | p->u.array=ty; 36 | return p; 37 | } 38 | 39 | Ty_ty Ty_Name(S_symbol sym, Ty_ty ty) 40 | {Ty_ty p = checked_malloc(sizeof(*p)); 41 | p->kind=Ty_name; 42 | p->u.name.sym=sym; 43 | p->u.name.ty=ty; 44 | return p; 45 | } 46 | 47 | 48 | Ty_tyList Ty_TyList(Ty_ty head, Ty_tyList tail) 49 | {Ty_tyList p = checked_malloc(sizeof(*p)); 50 | p->head=head; 51 | p->tail=tail; 52 | return p; 53 | } 54 | 55 | Ty_field Ty_Field(S_symbol name, Ty_ty ty) 56 | {Ty_field p = checked_malloc(sizeof(*p)); 57 | p->name=name; 58 | p->ty=ty; 59 | return p; 60 | } 61 | 62 | Ty_fieldList Ty_FieldList(Ty_field head, Ty_fieldList tail) 63 | {Ty_fieldList p = checked_malloc(sizeof(*p)); 64 | p->head=head; 65 | p->tail=tail; 66 | return p; 67 | } 68 | 69 | /* printing functions - used for debugging */ 70 | static char str_ty[][12] = { 71 | "ty_record", "ty_nil", "ty_int", "ty_string", 72 | "ty_array", "ty_name", "ty_void"}; 73 | 74 | /* This will infinite loop on mutually recursive types */ 75 | void Ty_print(Ty_ty t) 76 | { 77 | if (t == NULL) printf("null"); 78 | else { printf("%s", str_ty[t->kind]); 79 | if (t->kind == Ty_name) { 80 | printf(", %s", S_name(t->u.name.sym)); } 81 | } 82 | } 83 | 84 | void TyList_print(Ty_tyList list) 85 | { 86 | if (list == NULL) printf("null"); 87 | else { 88 | printf("TyList( "); 89 | Ty_print(list->head); 90 | printf(", "); 91 | TyList_print(list->tail); 92 | printf(")"); 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /chap5/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h - 3 | * 4 | * All types and functions declared in this header file begin with "Ty_" 5 | * Linked list types end with "..list" 6 | */ 7 | 8 | typedef struct Ty_ty_ *Ty_ty; 9 | typedef struct Ty_tyList_ *Ty_tyList; 10 | typedef struct Ty_field_ *Ty_field; 11 | typedef struct Ty_fieldList_ *Ty_fieldList; 12 | 13 | struct Ty_ty_ {enum {Ty_record, Ty_nil, Ty_int, Ty_string, Ty_array, 14 | Ty_name, Ty_void} kind; 15 | union {Ty_fieldList record; 16 | Ty_ty array; 17 | struct {S_symbol sym; Ty_ty ty;} name; 18 | } u; 19 | }; 20 | 21 | struct Ty_tyList_ {Ty_ty head; Ty_tyList tail;}; 22 | struct Ty_field_ {S_symbol name; Ty_ty ty;}; 23 | struct Ty_fieldList_ {Ty_field head; Ty_fieldList tail;}; 24 | 25 | Ty_ty Ty_Nil(void); 26 | Ty_ty Ty_Int(void); 27 | Ty_ty Ty_String(void); 28 | Ty_ty Ty_Void(void); 29 | 30 | Ty_ty Ty_Record(Ty_fieldList fields); 31 | Ty_ty Ty_Array(Ty_ty ty); 32 | Ty_ty Ty_Name(S_symbol sym, Ty_ty ty); 33 | 34 | Ty_tyList Ty_TyList(Ty_ty head, Ty_tyList tail); 35 | Ty_field Ty_Field(S_symbol name, Ty_ty ty); 36 | Ty_fieldList Ty_FieldList(Ty_field head, Ty_fieldList tail); 37 | 38 | void Ty_print(Ty_ty t); 39 | void TyList_print(Ty_tyList list); 40 | -------------------------------------------------------------------------------- /chap6/temp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * temp.c - functions to create and manipulate temporary variables which are 3 | * used in the IR tree representation before it has been determined 4 | * which variables are to go into registers. 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "util.h" 12 | #include "symbol.h" 13 | #include "temp.h" 14 | #include "table.h" 15 | 16 | struct Temp_temp_ {int num;}; 17 | 18 | string Temp_labelstring(Temp_label s) 19 | {return S_name(s); 20 | } 21 | 22 | static int labels = 0; 23 | 24 | Temp_label Temp_newlabel(void) 25 | {char buf[100]; 26 | sprintf(buf,"L%d",labels++); 27 | return Temp_namedlabel(String(buf)); 28 | } 29 | 30 | /* The label will be created only if it is not found. */ 31 | Temp_label Temp_namedlabel(string s) 32 | {return S_Symbol(s); 33 | } 34 | 35 | static int temps = 100; 36 | 37 | Temp_temp Temp_newtemp(void) 38 | {Temp_temp p = (Temp_temp) checked_malloc(sizeof (*p)); 39 | p->num=temps++; 40 | {char r[16]; 41 | sprintf(r, "%d", p->num); 42 | Temp_enter(Temp_name(), p, String(r)); 43 | } 44 | return p; 45 | } 46 | 47 | 48 | 49 | struct Temp_map_ {TAB_table tab; Temp_map under;}; 50 | 51 | 52 | Temp_map Temp_name(void) { 53 | static Temp_map m = NULL; 54 | if (!m) m=Temp_empty(); 55 | return m; 56 | } 57 | 58 | Temp_map newMap(TAB_table tab, Temp_map under) { 59 | Temp_map m = checked_malloc(sizeof(*m)); 60 | m->tab=tab; 61 | m->under=under; 62 | return m; 63 | } 64 | 65 | Temp_map Temp_empty(void) { 66 | return newMap(TAB_empty(), NULL); 67 | } 68 | 69 | Temp_map Temp_layerMap(Temp_map over, Temp_map under) { 70 | if (over==NULL) 71 | return under; 72 | else return newMap(over->tab, Temp_layerMap(over->under, under)); 73 | } 74 | 75 | void Temp_enter(Temp_map m, Temp_temp t, string s) { 76 | assert(m && m->tab); 77 | TAB_enter(m->tab,t,s); 78 | } 79 | 80 | string Temp_look(Temp_map m, Temp_temp t) { 81 | string s; 82 | assert(m && m->tab); 83 | s = TAB_look(m->tab, t); 84 | if (s) return s; 85 | else if (m->under) return Temp_look(m->under, t); 86 | else return NULL; 87 | } 88 | 89 | Temp_tempList Temp_TempList(Temp_temp h, Temp_tempList t) 90 | {Temp_tempList p = (Temp_tempList) checked_malloc(sizeof (*p)); 91 | p->head=h; p->tail=t; 92 | return p; 93 | } 94 | 95 | Temp_labelList Temp_LabelList(Temp_label h, Temp_labelList t) 96 | {Temp_labelList p = (Temp_labelList) checked_malloc(sizeof (*p)); 97 | p->head=h; p->tail=t; 98 | return p; 99 | } 100 | 101 | static FILE *outfile; 102 | void showit(Temp_temp t, string r) { 103 | fprintf(outfile, "t%d -> %s\n", t->num, r); 104 | } 105 | 106 | void Temp_dumpMap(FILE *out, Temp_map m) { 107 | outfile=out; 108 | TAB_dump(m->tab,(void (*)(void *, void*))showit); 109 | if (m->under) { 110 | fprintf(out,"---------\n"); 111 | Temp_dumpMap(out,m->under); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /chap6/temp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * temp.h 3 | * 4 | */ 5 | 6 | typedef struct Temp_temp_ *Temp_temp; 7 | Temp_temp Temp_newtemp(void); 8 | 9 | typedef struct Temp_tempList_ *Temp_tempList; 10 | struct Temp_tempList_ { Temp_temp head; Temp_tempList tail;}; 11 | Temp_tempList Temp_TempList(Temp_temp h, Temp_tempList t); 12 | 13 | typedef S_symbol Temp_label; 14 | Temp_label Temp_newlabel(void); 15 | Temp_label Temp_namedlabel(string name); 16 | string Temp_labelstring(Temp_label s); 17 | 18 | typedef struct Temp_labelList_ *Temp_labelList; 19 | struct Temp_labelList_ { Temp_label head; Temp_labelList tail;}; 20 | Temp_labelList Temp_LabelList(Temp_label h, Temp_labelList t); 21 | 22 | typedef struct Temp_map_ *Temp_map; 23 | Temp_map Temp_empty(void); 24 | Temp_map Temp_layerMap(Temp_map over, Temp_map under); 25 | void Temp_enter(Temp_map m, Temp_temp t, string s); 26 | string Temp_look(Temp_map m, Temp_temp t); 27 | void Temp_dumpMap(FILE *out, Temp_map m); 28 | 29 | Temp_map Temp_name(void); 30 | 31 | -------------------------------------------------------------------------------- /chap7/printtree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * printtree.c - functions to print out intermediate representation (IR) trees. 3 | * 4 | */ 5 | #include 6 | #include "util.h" 7 | #include "symbol.h" 8 | #include "temp.h" 9 | #include "tree.h" 10 | #include "printtree.h" 11 | 12 | /* local function prototype */ 13 | static void pr_tree_exp(FILE *out, T_exp exp, int d); 14 | 15 | static void indent(FILE *out, int d) { 16 | int i; 17 | for (i = 0; i <= d; i++) fprintf(out, " "); 18 | } 19 | 20 | static char bin_oper[][12] = { 21 | "PLUS", "MINUS", "TIMES", "DIVIDE", 22 | "AND", "OR", "LSHIFT", "RSHIFT", "ARSHIFT", "XOR"}; 23 | 24 | static char rel_oper[][12] = { 25 | "EQ", "NE", "LT", "GT", "LE", "GE", "ULT", "ULE", "UGT", "UGE"}; 26 | 27 | static void pr_stm(FILE *out, T_stm stm, int d) 28 | { 29 | switch (stm->kind) { 30 | case T_SEQ: 31 | indent(out,d); 32 | fprintf(out, "SEQ(\n"); pr_stm(out, stm->u.SEQ.left,d+1); fprintf(out, ",\n"); 33 | pr_stm(out, stm->u.SEQ.right,d+1); fprintf(out, ")"); 34 | break; 35 | case T_LABEL: 36 | indent(out,d); fprintf(out, "LABEL %s", S_name(stm->u.LABEL)); 37 | break; 38 | case T_JUMP: 39 | indent(out,d); fprintf(out, "JUMP(\n"); pr_tree_exp(out, stm->u.JUMP.exp,d+1); 40 | fprintf(out, ")"); 41 | break; 42 | case T_CJUMP: 43 | indent(out,d); fprintf(out, "CJUMP(%s,\n", rel_oper[stm->u.CJUMP.op]); 44 | pr_tree_exp(out, stm->u.CJUMP.left,d+1); fprintf(out, ",\n"); 45 | pr_tree_exp(out, stm->u.CJUMP.right,d+1); fprintf(out, ",\n"); 46 | indent(out,d+1); fprintf(out, "%s,", S_name(stm->u.CJUMP.true)); 47 | fprintf(out, "%s", S_name(stm->u.CJUMP.false)); fprintf(out, ")"); 48 | break; 49 | case T_MOVE: 50 | indent(out,d); fprintf(out, "MOVE(\n"); pr_tree_exp(out, stm->u.MOVE.dst,d+1); 51 | fprintf(out, ",\n"); 52 | pr_tree_exp(out, stm->u.MOVE.src,d+1); fprintf(out, ")"); 53 | break; 54 | case T_EXP: 55 | indent(out,d); fprintf(out, "EXP(\n"); pr_tree_exp(out, stm->u.EXP,d+1); 56 | fprintf(out, ")"); 57 | break; 58 | } 59 | } 60 | 61 | static void pr_tree_exp(FILE *out, T_exp exp, int d) 62 | { 63 | switch (exp->kind) { 64 | case T_BINOP: 65 | indent(out,d); fprintf(out, "BINOP(%s,\n", bin_oper[exp->u.BINOP.op]); 66 | pr_tree_exp(out, exp->u.BINOP.left,d+1); fprintf(out, ",\n"); 67 | pr_tree_exp(out, exp->u.BINOP.right,d+1); fprintf(out, ")"); 68 | break; 69 | case T_MEM: 70 | indent(out,d); fprintf(out, "MEM"); 71 | fprintf(out, "(\n"); pr_tree_exp(out, exp->u.MEM,d+1); fprintf(out, ")"); 72 | break; 73 | case T_TEMP: 74 | indent(out,d); fprintf(out, "TEMP t%s", 75 | Temp_look(Temp_name(), exp->u.TEMP)); 76 | break; 77 | case T_ESEQ: 78 | indent(out,d); fprintf(out, "ESEQ(\n"); pr_stm(out, exp->u.ESEQ.stm,d+1); 79 | fprintf(out, ",\n"); 80 | pr_tree_exp(out, exp->u.ESEQ.exp,d+1); fprintf(out, ")"); 81 | break; 82 | case T_NAME: 83 | indent(out,d); fprintf(out, "NAME %s", S_name(exp->u.NAME)); 84 | break; 85 | case T_CONST: 86 | indent(out,d); fprintf(out, "CONST %d", exp->u.CONST); 87 | break; 88 | case T_CALL: 89 | {T_expList args = exp->u.CALL.args; 90 | indent(out,d); fprintf(out, "CALL(\n"); pr_tree_exp(out, exp->u.CALL.fun,d+1); 91 | for (;args; args=args->tail) { 92 | fprintf(out, ",\n"); pr_tree_exp(out, args->head,d+2); 93 | } 94 | fprintf(out, ")"); 95 | break; 96 | } 97 | } /* end of switch */ 98 | } 99 | 100 | void printStmList (FILE *out, T_stmList stmList) 101 | { 102 | for (; stmList; stmList=stmList->tail) { 103 | pr_stm(out, stmList->head,0); fprintf(out, "\n"); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /chap7/printtree.h: -------------------------------------------------------------------------------- 1 | /* function prototype from printtree.c */ 2 | void printStmList (FILE *out, T_stmList stmList) ; 3 | 4 | -------------------------------------------------------------------------------- /chap7/tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.h" 3 | #include "symbol.h" 4 | #include "temp.h" 5 | #include "tree.h" 6 | 7 | T_expList T_ExpList(T_exp head, T_expList tail) 8 | {T_expList p = (T_expList) checked_malloc (sizeof *p); 9 | p->head=head; p->tail=tail; 10 | return p; 11 | } 12 | 13 | T_stmList T_StmList(T_stm head, T_stmList tail) 14 | {T_stmList p = (T_stmList) checked_malloc (sizeof *p); 15 | p->head=head; p->tail=tail; 16 | return p; 17 | } 18 | 19 | T_stm T_Seq(T_stm left, T_stm right) 20 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 21 | p->kind=T_SEQ; 22 | p->u.SEQ.left=left; 23 | p->u.SEQ.right=right; 24 | return p; 25 | } 26 | 27 | T_stm T_Label(Temp_label label) 28 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 29 | p->kind=T_LABEL; 30 | p->u.LABEL=label; 31 | return p; 32 | } 33 | 34 | T_stm T_Jump(T_exp exp, Temp_labelList labels) 35 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 36 | p->kind=T_JUMP; 37 | p->u.JUMP.exp=exp; 38 | p->u.JUMP.jumps=labels; 39 | return p; 40 | } 41 | 42 | T_stm T_Cjump(T_relOp op, T_exp left, T_exp right, 43 | Temp_label true, Temp_label false) 44 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 45 | p->kind=T_CJUMP; 46 | p->u.CJUMP.op=op; p->u.CJUMP.left=left; p->u.CJUMP.right=right; 47 | p->u.CJUMP.true=true; 48 | p->u.CJUMP.false=false; 49 | return p; 50 | } 51 | 52 | T_stm T_Move(T_exp dst, T_exp src) 53 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 54 | p->kind=T_MOVE; 55 | p->u.MOVE.dst=dst; 56 | p->u.MOVE.src=src; 57 | return p; 58 | } 59 | 60 | T_stm T_Exp(T_exp exp) 61 | {T_stm p = (T_stm) checked_malloc(sizeof *p); 62 | p->kind=T_EXP; 63 | p->u.EXP=exp; 64 | return p; 65 | } 66 | 67 | T_exp T_Binop(T_binOp op, T_exp left, T_exp right) 68 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 69 | p->kind=T_BINOP; 70 | p->u.BINOP.op=op; 71 | p->u.BINOP.left=left; 72 | p->u.BINOP.right=right; 73 | return p; 74 | } 75 | 76 | T_exp T_Mem(T_exp exp) 77 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 78 | p->kind=T_MEM; 79 | p->u.MEM=exp; 80 | return p; 81 | } 82 | 83 | T_exp T_Temp(Temp_temp temp) 84 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 85 | p->kind=T_TEMP; 86 | p->u.TEMP=temp; 87 | return p; 88 | } 89 | 90 | T_exp T_Eseq(T_stm stm, T_exp exp) 91 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 92 | p->kind=T_ESEQ; 93 | p->u.ESEQ.stm=stm; 94 | p->u.ESEQ.exp=exp; 95 | return p; 96 | } 97 | 98 | T_exp T_Name(Temp_label name) 99 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 100 | p->kind=T_NAME; 101 | p->u.NAME=name; 102 | return p; 103 | } 104 | 105 | T_exp T_Const(int consti) 106 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 107 | p->kind=T_CONST; 108 | p->u.CONST=consti; 109 | return p; 110 | } 111 | 112 | T_exp T_Call(T_exp fun, T_expList args) 113 | {T_exp p = (T_exp) checked_malloc(sizeof *p); 114 | p->kind=T_CALL; 115 | p->u.CALL.fun=fun; 116 | p->u.CALL.args=args; 117 | return p; 118 | } 119 | 120 | T_relOp T_notRel(T_relOp r) 121 | { 122 | switch(r) 123 | {case T_eq: return T_ne; 124 | case T_ne: return T_eq; 125 | case T_lt: return T_ge; 126 | case T_ge: return T_lt; 127 | case T_gt: return T_le; 128 | case T_le: return T_gt; 129 | case T_ult: return T_uge; 130 | case T_uge: return T_ult; 131 | case T_ule: return T_ugt ; 132 | case T_ugt: return T_ule; 133 | } 134 | assert(0); return 0; 135 | } 136 | 137 | T_relOp T_commute(T_relOp r) 138 | {switch(r) { 139 | case T_eq: return T_eq; 140 | case T_ne: return T_ne; 141 | case T_lt: return T_gt; 142 | case T_ge: return T_le; 143 | case T_gt: return T_lt ; 144 | case T_le: return T_ge; 145 | case T_ult: return T_ugt; 146 | case T_uge: return T_ule; 147 | case T_ule: return T_uge ; 148 | case T_ugt: return T_ult; 149 | } 150 | assert(0); return 0; 151 | } 152 | 153 | 154 | -------------------------------------------------------------------------------- /chap7/tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tree.h - Definitions for intermediate representation (IR) trees. 3 | * 4 | */ 5 | typedef struct T_stm_ *T_stm; 6 | typedef struct T_exp_ *T_exp; 7 | typedef struct T_expList_ *T_expList; 8 | struct T_expList_ {T_exp head; T_expList tail;}; 9 | typedef struct T_stmList_ *T_stmList; 10 | struct T_stmList_ {T_stm head; T_stmList tail;}; 11 | 12 | typedef enum {T_plus, T_minus, T_mul, T_div, 13 | T_and, T_or, T_lshift, T_rshift, T_arshift, T_xor} T_binOp ; 14 | 15 | typedef enum {T_eq, T_ne, T_lt, T_gt, T_le, T_ge, 16 | T_ult, T_ule, T_ugt, T_uge} T_relOp; 17 | 18 | struct T_stm_ {enum {T_SEQ, T_LABEL, T_JUMP, T_CJUMP, T_MOVE, 19 | T_EXP} kind; 20 | union {struct {T_stm left, right;} SEQ; 21 | Temp_label LABEL; 22 | struct {T_exp exp; Temp_labelList jumps;} JUMP; 23 | struct {T_relOp op; T_exp left, right; 24 | Temp_label true, false;} CJUMP; 25 | struct {T_exp dst, src;} MOVE; 26 | T_exp EXP; 27 | } u; 28 | }; 29 | 30 | struct T_exp_ {enum {T_BINOP, T_MEM, T_TEMP, T_ESEQ, T_NAME, 31 | T_CONST, T_CALL} kind; 32 | union {struct {T_binOp op; T_exp left, right;} BINOP; 33 | T_exp MEM; 34 | Temp_temp TEMP; 35 | struct {T_stm stm; T_exp exp;} ESEQ; 36 | Temp_label NAME; 37 | int CONST; 38 | struct {T_exp fun; T_expList args;} CALL; 39 | } u; 40 | }; 41 | 42 | T_expList T_ExpList (T_exp head, T_expList tail); 43 | T_stmList T_StmList (T_stm head, T_stmList tail); 44 | 45 | T_stm T_Seq(T_stm left, T_stm right); 46 | T_stm T_Label(Temp_label); 47 | T_stm T_Jump(T_exp exp, Temp_labelList labels); 48 | T_stm T_Cjump(T_relOp op, T_exp left, T_exp right, 49 | Temp_label true, Temp_label false); 50 | T_stm T_Move(T_exp, T_exp); 51 | T_stm T_Exp(T_exp); 52 | 53 | T_exp T_Binop(T_binOp, T_exp, T_exp); 54 | T_exp T_Mem(T_exp); 55 | T_exp T_Temp(Temp_temp); 56 | T_exp T_Eseq(T_stm, T_exp); 57 | T_exp T_Name(Temp_label); 58 | T_exp T_Const(int); 59 | T_exp T_Call(T_exp, T_expList); 60 | 61 | T_relOp T_notRel(T_relOp); /* a op b == not(a notRel(op) b) */ 62 | T_relOp T_commute(T_relOp); /* a op b == b commute(op) a */ 63 | -------------------------------------------------------------------------------- /chap8/canon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * canon.c - Functions to convert the IR trees into basic blocks and traces. 3 | * 4 | */ 5 | #include 6 | #include "util.h" 7 | #include "symbol.h" 8 | #include "temp.h" 9 | #include "tree.h" 10 | #include "canon.h" 11 | 12 | typedef struct expRefList_ *expRefList; 13 | struct expRefList_ {T_exp *head; expRefList tail;}; 14 | 15 | /* local function prototypes */ 16 | static T_stm do_stm(T_stm stm); 17 | static struct stmExp do_exp(T_exp exp); 18 | static C_stmListList mkBlocks(T_stmList stms, Temp_label done); 19 | static T_stmList getNext(void); 20 | 21 | static expRefList ExpRefList(T_exp *head, expRefList tail) 22 | {expRefList p = (expRefList) checked_malloc (sizeof *p); 23 | p->head=head; p->tail=tail; 24 | return p; 25 | } 26 | 27 | static bool isNop(T_stm x) 28 | { return x->kind == T_EXP && x->u.EXP->kind == T_CONST; 29 | } 30 | 31 | static T_stm seq(T_stm x, T_stm y) 32 | { 33 | if (isNop(x)) return y; 34 | if (isNop(y)) return x; 35 | return T_Seq(x,y); 36 | } 37 | 38 | static bool commute(T_stm x, T_exp y) 39 | { 40 | if (isNop(x)) return TRUE; 41 | if (y->kind == T_NAME || y->kind == T_CONST) return TRUE; 42 | return FALSE; 43 | } 44 | 45 | struct stmExp {T_stm s; T_exp e;}; 46 | 47 | static T_stm reorder(expRefList rlist) { 48 | if (!rlist) return T_Exp(T_Const(0)); /* nop */ 49 | else if ((*rlist->head)->kind==T_CALL) { 50 | Temp_temp t = Temp_newtemp(); 51 | *rlist->head = T_Eseq(T_Move(T_Temp(t),*rlist->head),T_Temp(t)); 52 | return reorder(rlist); 53 | } 54 | else { 55 | struct stmExp hd = do_exp(*rlist->head); 56 | T_stm s = reorder(rlist->tail); 57 | if (commute(s,hd.e)) { 58 | *rlist->head=hd.e; 59 | return seq(hd.s,s); 60 | } else { 61 | Temp_temp t = Temp_newtemp(); 62 | *rlist->head=T_Temp(t); 63 | return seq(hd.s, seq(T_Move(T_Temp(t),hd.e), s)); 64 | } 65 | } 66 | } 67 | 68 | static expRefList get_call_rlist(T_exp exp) 69 | {expRefList rlist, curr; 70 | T_expList args = exp->u.CALL.args; 71 | curr = rlist = ExpRefList(&exp->u.CALL.fun, NULL); 72 | for (;args; args=args->tail) { 73 | curr = curr->tail = ExpRefList(&args->head, NULL); 74 | } 75 | return rlist; 76 | } 77 | 78 | static struct stmExp StmExp(T_stm stm, T_exp exp) { 79 | struct stmExp x; 80 | x.s = stm; 81 | x.e = exp; 82 | return x; 83 | } 84 | 85 | static struct stmExp do_exp(T_exp exp) 86 | { 87 | switch(exp->kind) { 88 | case T_BINOP: 89 | return StmExp(reorder(ExpRefList(&exp->u.BINOP.left, 90 | ExpRefList(&exp->u.BINOP.right, NULL))), 91 | exp); 92 | case T_MEM: 93 | return StmExp(reorder(ExpRefList(&exp->u.MEM, NULL)), exp); 94 | case T_ESEQ: 95 | {struct stmExp x = do_exp(exp->u.ESEQ.exp); 96 | return StmExp(seq(do_stm(exp->u.ESEQ.stm), x.s), x.e); 97 | } 98 | case T_CALL: 99 | return StmExp(reorder(get_call_rlist(exp)), exp); 100 | default: 101 | return StmExp(reorder(NULL), exp); 102 | } 103 | } 104 | 105 | /* processes stm so that it contains no ESEQ nodes */ 106 | static T_stm do_stm(T_stm stm) 107 | { 108 | switch (stm->kind) { 109 | case T_SEQ: 110 | return seq(do_stm(stm->u.SEQ.left), do_stm(stm->u.SEQ.right)); 111 | case T_JUMP: 112 | return seq(reorder(ExpRefList(&stm->u.JUMP.exp, NULL)), stm); 113 | case T_CJUMP: 114 | return seq(reorder(ExpRefList(&stm->u.CJUMP.left, 115 | ExpRefList(&stm->u.CJUMP.right,NULL))), stm); 116 | case T_MOVE: 117 | if (stm->u.MOVE.dst->kind == T_TEMP && stm->u.MOVE.src->kind == T_CALL) 118 | return seq(reorder(get_call_rlist(stm->u.MOVE.src)), stm); 119 | else if (stm->u.MOVE.dst->kind == T_TEMP) 120 | return seq(reorder(ExpRefList(&stm->u.MOVE.src, NULL)), stm); 121 | else if (stm->u.MOVE.dst->kind == T_MEM) 122 | return seq(reorder(ExpRefList(&stm->u.MOVE.dst->u.MEM, 123 | ExpRefList(&stm->u.MOVE.src, NULL))), stm); 124 | else if (stm->u.MOVE.dst->kind == T_ESEQ) { 125 | T_stm s = stm->u.MOVE.dst->u.ESEQ.stm; 126 | stm->u.MOVE.dst = stm->u.MOVE.dst->u.ESEQ.exp; 127 | return do_stm(T_Seq(s, stm)); 128 | } 129 | assert(0); /* dst should be temp or mem only */ 130 | case T_EXP: 131 | if (stm->u.EXP->kind == T_CALL) 132 | return seq(reorder(get_call_rlist(stm->u.EXP)), stm); 133 | else return seq(reorder(ExpRefList(&stm->u.EXP, NULL)), stm); 134 | default: 135 | return stm; 136 | } 137 | } 138 | 139 | /* linear gets rid of the top-level SEQ's, producing a list */ 140 | static T_stmList linear(T_stm stm, T_stmList right) 141 | { 142 | if (stm->kind == T_SEQ) 143 | return linear(stm->u.SEQ.left,linear(stm->u.SEQ.right,right)); 144 | else return T_StmList(stm, right); 145 | } 146 | 147 | /* From an arbitrary Tree statement, produce a list of cleaned trees 148 | satisfying the following properties: 149 | 1. No SEQ's or ESEQ's 150 | 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) */ 151 | T_stmList C_linearize(T_stm stm) 152 | { 153 | return linear(do_stm(stm), NULL); 154 | } 155 | 156 | static C_stmListList StmListList(T_stmList head, C_stmListList tail) 157 | {C_stmListList p = (C_stmListList) checked_malloc (sizeof *p); 158 | p->head=head; p->tail=tail; 159 | return p; 160 | } 161 | 162 | /* Go down a list looking for end of basic block */ 163 | static C_stmListList next(T_stmList prevstms, T_stmList stms, Temp_label done) 164 | { 165 | if (!stms) 166 | return next(prevstms, 167 | T_StmList(T_Jump(T_Name(done), Temp_LabelList(done, NULL)), 168 | NULL), done); 169 | if (stms->head->kind == T_JUMP || stms->head->kind == T_CJUMP) { 170 | C_stmListList stmLists; 171 | prevstms->tail = stms; 172 | stmLists = mkBlocks(stms->tail, done); 173 | stms->tail = NULL; 174 | return stmLists; 175 | } 176 | else if (stms->head->kind == T_LABEL) { 177 | Temp_label lab = stms->head->u.LABEL; 178 | return next(prevstms, T_StmList(T_Jump(T_Name(lab), Temp_LabelList(lab, NULL)), 179 | stms), done); 180 | } 181 | else { 182 | prevstms->tail = stms; 183 | return next(stms, stms->tail, done); 184 | } 185 | } 186 | 187 | /* Create the beginning of a basic block */ 188 | static C_stmListList mkBlocks(T_stmList stms, Temp_label done) 189 | { 190 | if (!stms) { 191 | return NULL; 192 | } 193 | if (stms->head->kind != T_LABEL) { 194 | return mkBlocks(T_StmList(T_Label(Temp_newlabel()), stms), done); 195 | } 196 | /* else there already is a label */ 197 | return StmListList(stms, next(stms, stms->tail, done)); 198 | } 199 | 200 | /* basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) 201 | From a list of cleaned trees, produce a list of 202 | basic blocks satisfying the following properties: 203 | 1. and 2. as above; 204 | 3. Every block begins with a LABEL; 205 | 4. A LABEL appears only at the beginning of a block; 206 | 5. Any JUMP or CJUMP is the last stm in a block; 207 | 6. Every block ends with a JUMP or CJUMP; 208 | Also produce the "label" to which control will be passed 209 | upon exit. 210 | */ 211 | struct C_block C_basicBlocks(T_stmList stmList) 212 | { 213 | struct C_block b; 214 | b.label = Temp_newlabel(); 215 | b.stmLists = mkBlocks(stmList, b.label); 216 | 217 | return b; 218 | } 219 | 220 | static S_table block_env; 221 | static struct C_block global_block; 222 | 223 | static T_stmList getLast(T_stmList list) 224 | { 225 | T_stmList last = list; 226 | while (last->tail->tail) last = last->tail; 227 | return last; 228 | } 229 | 230 | static void trace(T_stmList list) 231 | { 232 | T_stmList last = getLast(list); 233 | T_stm lab = list->head; 234 | T_stm s = last->tail->head; 235 | S_enter(block_env, lab->u.LABEL, NULL); 236 | if (s->kind == T_JUMP) { 237 | T_stmList target = (T_stmList) S_look(block_env, s->u.JUMP.jumps->head); 238 | if (!s->u.JUMP.jumps->tail && target) { 239 | last->tail = target; /* merge the 2 lists removing JUMP stm */ 240 | trace(target); 241 | } 242 | else last->tail->tail = getNext(); /* merge and keep JUMP stm */ 243 | } 244 | /* we want false label to follow CJUMP */ 245 | else if (s->kind == T_CJUMP) { 246 | T_stmList true = (T_stmList) S_look(block_env, s->u.CJUMP.true); 247 | T_stmList false = (T_stmList) S_look(block_env, s->u.CJUMP.false); 248 | if (false) { 249 | last->tail->tail = false; 250 | trace(false); 251 | } 252 | else if (true) { /* convert so that existing label is a false label */ 253 | last->tail->head = T_Cjump(T_notRel(s->u.CJUMP.op), s->u.CJUMP.left, 254 | s->u.CJUMP.right, s->u.CJUMP.false, 255 | s->u.CJUMP.true); 256 | last->tail->tail = true; 257 | trace(true); 258 | } 259 | else { 260 | Temp_label false = Temp_newlabel(); 261 | last->tail->head = T_Cjump(s->u.CJUMP.op, s->u.CJUMP.left, 262 | s->u.CJUMP.right, s->u.CJUMP.true, false); 263 | last->tail->tail = T_StmList(T_Label(false), getNext()); 264 | } 265 | } 266 | else assert(0); 267 | } 268 | 269 | /* get the next block from the list of stmLists, using only those that have 270 | * not been traced yet */ 271 | static T_stmList getNext() 272 | { 273 | if (!global_block.stmLists) 274 | return T_StmList(T_Label(global_block.label), NULL); 275 | else { 276 | T_stmList s = global_block.stmLists->head; 277 | if (S_look(block_env, s->head->u.LABEL)) {/* label exists in the table */ 278 | trace(s); 279 | return s; 280 | } 281 | else { 282 | global_block.stmLists = global_block.stmLists->tail; 283 | return getNext(); 284 | } 285 | } 286 | } 287 | /* traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list 288 | From a list of basic blocks satisfying properties 1-6, 289 | along with an "exit" label, 290 | produce a list of stms such that: 291 | 1. and 2. as above; 292 | 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. 293 | The blocks are reordered to satisfy property 7; also 294 | in this reordering as many JUMP(T.NAME(lab)) statements 295 | as possible are eliminated by falling through into T.LABEL(lab). 296 | */ 297 | T_stmList C_traceSchedule(struct C_block b) 298 | { C_stmListList sList; 299 | block_env = S_empty(); 300 | global_block = b; 301 | 302 | for (sList=global_block.stmLists; sList; sList=sList->tail) { 303 | S_enter(block_env, sList->head->head->u.LABEL, sList->head); 304 | } 305 | 306 | return getNext(); 307 | } 308 | 309 | -------------------------------------------------------------------------------- /chap8/canon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * canon.h - Definitions for canon.c which converts the IR trees into 3 | * basic blocks and traces. 4 | * 5 | */ 6 | typedef struct C_stmListList_ *C_stmListList; 7 | struct C_block { C_stmListList stmLists; Temp_label label;}; 8 | struct C_stmListList_ { T_stmList head; C_stmListList tail;}; 9 | 10 | T_stmList C_linearize(T_stm stm); 11 | /* From an arbitrary Tree statement, produce a list of cleaned trees 12 | satisfying the following properties: 13 | 1. No SEQ's or ESEQ's 14 | 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) 15 | */ 16 | 17 | struct C_block C_basicBlocks(T_stmList stmList); 18 | /* basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) 19 | From a list of cleaned trees, produce a list of 20 | basic blocks satisfying the following properties: 21 | 1. and 2. as above; 22 | 3. Every block begins with a LABEL; 23 | 4. A LABEL appears only at the beginning of a block; 24 | 5. Any JUMP or CJUMP is the last stm in a block; 25 | 6. Every block ends with a JUMP or CJUMP; 26 | Also produce the "label" to which control will be passed 27 | upon exit. 28 | */ 29 | 30 | T_stmList C_traceSchedule(struct C_block b); 31 | /* traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list 32 | From a list of basic blocks satisfying properties 1-6, 33 | along with an "exit" label, 34 | produce a list of stms such that: 35 | 1. and 2. as above; 36 | 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. 37 | The blocks are reordered to satisfy property 7; also 38 | in this reordering as many JUMP(T.NAME(lab)) statements 39 | as possible are eliminated by falling through into T.LABEL(lab). 40 | */ 41 | 42 | -------------------------------------------------------------------------------- /chap9/assem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mipscodegen.c - Functions to translate to Assem-instructions for 3 | * the Jouette assembly language using Maximal Munch. 4 | */ 5 | 6 | #include 7 | #include /* for atoi */ 8 | #include /* for strcpy */ 9 | #include "util.h" 10 | #include "symbol.h" 11 | #include "absyn.h" 12 | #include "temp.h" 13 | #include "tree.h" 14 | #include "assem.h" 15 | #include "frame.h" 16 | #include "errormsg.h" 17 | 18 | AS_targets AS_Targets(Temp_labelList labels) { 19 | AS_targets p = checked_malloc (sizeof *p); 20 | p->labels=labels; 21 | return p; 22 | } 23 | 24 | AS_instr AS_Oper(string a, Temp_tempList d, Temp_tempList s, AS_targets j) { 25 | AS_instr p = (AS_instr) checked_malloc (sizeof *p); 26 | p->kind = I_OPER; 27 | p->u.OPER.assem=a; 28 | p->u.OPER.dst=d; 29 | p->u.OPER.src=s; 30 | p->u.OPER.jumps=j; 31 | return p; 32 | } 33 | 34 | AS_instr AS_Label(string a, Temp_label label) { 35 | AS_instr p = (AS_instr) checked_malloc (sizeof *p); 36 | p->kind = I_LABEL; 37 | p->u.LABEL.assem=a; 38 | p->u.LABEL.label=label; 39 | return p; 40 | } 41 | 42 | AS_instr AS_Move(string a, Temp_tempList d, Temp_tempList s) { 43 | AS_instr p = (AS_instr) checked_malloc (sizeof *p); 44 | p->kind = I_MOVE; 45 | p->u.MOVE.assem=a; 46 | p->u.MOVE.dst=d; 47 | p->u.MOVE.src=s; 48 | return p; 49 | } 50 | 51 | AS_instrList AS_InstrList(AS_instr head, AS_instrList tail) 52 | {AS_instrList p = (AS_instrList) checked_malloc (sizeof *p); 53 | p->head=head; p->tail=tail; 54 | return p; 55 | } 56 | 57 | /* put list b at the end of list a */ 58 | AS_instrList AS_splice(AS_instrList a, AS_instrList b) { 59 | AS_instrList p; 60 | if (a==NULL) return b; 61 | for(p=a; p->tail!=NULL; p=p->tail) ; 62 | p->tail=b; 63 | return a; 64 | } 65 | 66 | static Temp_temp nthTemp(Temp_tempList list, int i) { 67 | assert(list); 68 | if (i==0) return list->head; 69 | else return nthTemp(list->tail,i-1); 70 | } 71 | 72 | static Temp_label nthLabel(Temp_labelList list, int i) { 73 | assert(list); 74 | if (i==0) return list->head; 75 | else return nthLabel(list->tail,i-1); 76 | } 77 | 78 | 79 | /* first param is string created by this function by reading 'assem' string 80 | * and replacing `d `s and `j stuff. 81 | * Last param is function to use to determine what to do with each temp. 82 | */ 83 | static void format(char *result, string assem, 84 | Temp_tempList dst, Temp_tempList src, 85 | AS_targets jumps, Temp_map m) 86 | { 87 | char *p; 88 | int i = 0; /* offset to result string */ 89 | for(p = assem; p && *p != '\0'; p++) 90 | if (*p == '`') 91 | switch(*(++p)) { 92 | case 's': {int n = atoi(++p); 93 | string s = Temp_look(m, nthTemp(src,n)); 94 | strcpy(result+i, s); 95 | i += strlen(s); 96 | } 97 | break; 98 | case 'd': {int n = atoi(++p); 99 | string s = Temp_look(m, nthTemp(dst,n)); 100 | strcpy(result+i, s); 101 | i += strlen(s); 102 | } 103 | break; 104 | case 'j': assert(jumps); 105 | {int n = atoi(++p); 106 | string s = Temp_labelstring(nthLabel(jumps->labels,n)); 107 | strcpy(result+i, s); 108 | i += strlen(s); 109 | } 110 | break; 111 | case '`': result[i] = '`'; i++; 112 | break; 113 | default: assert(0); 114 | } 115 | else {result[i] = *p; i++; } 116 | result[i] = '\0'; 117 | } 118 | 119 | 120 | void AS_print(FILE *out, AS_instr i, Temp_map m) 121 | { 122 | char r[200]; /* result */ 123 | switch (i->kind) { 124 | case I_OPER: 125 | format(r, i->u.OPER.assem, i->u.OPER.dst, i->u.OPER.src, i->u.OPER.jumps, m); 126 | fprintf(out, "%s", r); 127 | break; 128 | case I_LABEL: 129 | format(r, i->u.LABEL.assem, NULL, NULL, NULL, m); 130 | fprintf(out, "%s", r); 131 | /* i->u.LABEL->label); */ 132 | break; 133 | case I_MOVE: 134 | format(r, i->u.MOVE.assem, i->u.MOVE.dst, i->u.MOVE.src, NULL, m); 135 | fprintf(out, "%s", r); 136 | break; 137 | } 138 | } 139 | 140 | /* c should be COL_color; temporarily it is not */ 141 | void AS_printInstrList (FILE *out, AS_instrList iList, Temp_map m) 142 | { 143 | for (; iList; iList=iList->tail) { 144 | AS_print(out, iList->head, m); 145 | } 146 | fprintf(out, "\n"); 147 | } 148 | 149 | AS_proc AS_Proc(string p, AS_instrList b, string e) 150 | {AS_proc proc = checked_malloc(sizeof(*proc)); 151 | proc->prolog=p; proc->body=b; proc->epilog=e; 152 | return proc; 153 | } 154 | -------------------------------------------------------------------------------- /chap9/assem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * assem.h - Function prototypes to translate to Assem-instructions 3 | * using Maximal Munch. 4 | */ 5 | 6 | typedef struct {Temp_labelList labels;} *AS_targets; 7 | AS_targets AS_Targets(Temp_labelList labels); 8 | 9 | typedef struct AS_instr_ *AS_instr; 10 | struct AS_instr_ { enum {I_OPER, I_LABEL, I_MOVE} kind; 11 | union {struct {string assem; Temp_tempList dst, src; 12 | AS_targets jumps;} OPER; 13 | struct {string assem; Temp_label label;} LABEL; 14 | struct {string assem; Temp_tempList dst, src;} MOVE; 15 | } u; 16 | }; 17 | 18 | AS_instr AS_Oper(string a, Temp_tempList d, Temp_tempList s, AS_targets j); 19 | AS_instr AS_Label(string a, Temp_label label); 20 | AS_instr AS_Move(string a, Temp_tempList d, Temp_tempList s); 21 | 22 | void AS_print(FILE *out, AS_instr i, Temp_map m); 23 | 24 | typedef struct AS_instrList_ *AS_instrList; 25 | struct AS_instrList_ { AS_instr head; AS_instrList tail;}; 26 | AS_instrList AS_InstrList(AS_instr head, AS_instrList tail); 27 | 28 | AS_instrList AS_splice(AS_instrList a, AS_instrList b); 29 | void AS_printInstrList (FILE *out, AS_instrList iList, Temp_map m); 30 | 31 | typedef struct AS_proc_ *AS_proc; 32 | struct AS_proc_ { 33 | string prolog; 34 | AS_instrList body; 35 | string epilog; 36 | }; 37 | 38 | AS_proc AS_Proc(string p, AS_instrList b, string e); 39 | -------------------------------------------------------------------------------- /chap9/canon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * canon.c - Functions to convert the IR trees into basic blocks and traces. 3 | * 4 | */ 5 | #include 6 | #include "util.h" 7 | #include "symbol.h" 8 | #include "temp.h" 9 | #include "tree.h" 10 | #include "canon.h" 11 | 12 | typedef struct expRefList_ *expRefList; 13 | struct expRefList_ {T_exp *head; expRefList tail;}; 14 | 15 | /* local function prototypes */ 16 | static T_stm do_stm(T_stm stm); 17 | static struct stmExp do_exp(T_exp exp); 18 | static C_stmListList mkBlocks(T_stmList stms, Temp_label done); 19 | static T_stmList getNext(void); 20 | 21 | static expRefList ExpRefList(T_exp *head, expRefList tail) 22 | {expRefList p = (expRefList) checked_malloc (sizeof *p); 23 | p->head=head; p->tail=tail; 24 | return p; 25 | } 26 | 27 | static bool isNop(T_stm x) 28 | { return x->kind == T_EXP && x->u.EXP->kind == T_CONST; 29 | } 30 | 31 | static T_stm seq(T_stm x, T_stm y) 32 | { 33 | if (isNop(x)) return y; 34 | if (isNop(y)) return x; 35 | return T_Seq(x,y); 36 | } 37 | 38 | static bool commute(T_stm x, T_exp y) 39 | { 40 | if (isNop(x)) return TRUE; 41 | if (y->kind == T_NAME || y->kind == T_CONST) return TRUE; 42 | return FALSE; 43 | } 44 | 45 | struct stmExp {T_stm s; T_exp e;}; 46 | 47 | static T_stm reorder(expRefList rlist) { 48 | if (!rlist) return T_Exp(T_Const(0)); /* nop */ 49 | else if ((*rlist->head)->kind==T_CALL) { 50 | Temp_temp t = Temp_newtemp(); 51 | *rlist->head = T_Eseq(T_Move(T_Temp(t),*rlist->head),T_Temp(t)); 52 | return reorder(rlist); 53 | } 54 | else { 55 | struct stmExp hd = do_exp(*rlist->head); 56 | T_stm s = reorder(rlist->tail); 57 | if (commute(s,hd.e)) { 58 | *rlist->head=hd.e; 59 | return seq(hd.s,s); 60 | } else { 61 | Temp_temp t = Temp_newtemp(); 62 | *rlist->head=T_Temp(t); 63 | return seq(hd.s, seq(T_Move(T_Temp(t),hd.e), s)); 64 | } 65 | } 66 | } 67 | 68 | static expRefList get_call_rlist(T_exp exp) 69 | {expRefList rlist, curr; 70 | T_expList args = exp->u.CALL.args; 71 | curr = rlist = ExpRefList(&exp->u.CALL.fun, NULL); 72 | for (;args; args=args->tail) { 73 | curr = curr->tail = ExpRefList(&args->head, NULL); 74 | } 75 | return rlist; 76 | } 77 | 78 | static struct stmExp StmExp(T_stm stm, T_exp exp) { 79 | struct stmExp x; 80 | x.s = stm; 81 | x.e = exp; 82 | return x; 83 | } 84 | 85 | static struct stmExp do_exp(T_exp exp) 86 | { 87 | switch(exp->kind) { 88 | case T_BINOP: 89 | return StmExp(reorder(ExpRefList(&exp->u.BINOP.left, 90 | ExpRefList(&exp->u.BINOP.right, NULL))), 91 | exp); 92 | case T_MEM: 93 | return StmExp(reorder(ExpRefList(&exp->u.MEM, NULL)), exp); 94 | case T_ESEQ: 95 | {struct stmExp x = do_exp(exp->u.ESEQ.exp); 96 | return StmExp(seq(do_stm(exp->u.ESEQ.stm), x.s), x.e); 97 | } 98 | case T_CALL: 99 | return StmExp(reorder(get_call_rlist(exp)), exp); 100 | default: 101 | return StmExp(reorder(NULL), exp); 102 | } 103 | } 104 | 105 | /* processes stm so that it contains no ESEQ nodes */ 106 | static T_stm do_stm(T_stm stm) 107 | { 108 | switch (stm->kind) { 109 | case T_SEQ: 110 | return seq(do_stm(stm->u.SEQ.left), do_stm(stm->u.SEQ.right)); 111 | case T_JUMP: 112 | return seq(reorder(ExpRefList(&stm->u.JUMP.exp, NULL)), stm); 113 | case T_CJUMP: 114 | return seq(reorder(ExpRefList(&stm->u.CJUMP.left, 115 | ExpRefList(&stm->u.CJUMP.right,NULL))), stm); 116 | case T_MOVE: 117 | if (stm->u.MOVE.dst->kind == T_TEMP && stm->u.MOVE.src->kind == T_CALL) 118 | return seq(reorder(get_call_rlist(stm->u.MOVE.src)), stm); 119 | else if (stm->u.MOVE.dst->kind == T_TEMP) 120 | return seq(reorder(ExpRefList(&stm->u.MOVE.src, NULL)), stm); 121 | else if (stm->u.MOVE.dst->kind == T_MEM) 122 | return seq(reorder(ExpRefList(&stm->u.MOVE.dst->u.MEM, 123 | ExpRefList(&stm->u.MOVE.src, NULL))), stm); 124 | else if (stm->u.MOVE.dst->kind == T_ESEQ) { 125 | T_stm s = stm->u.MOVE.dst->u.ESEQ.stm; 126 | stm->u.MOVE.dst = stm->u.MOVE.dst->u.ESEQ.exp; 127 | return do_stm(T_Seq(s, stm)); 128 | } 129 | assert(0); /* dst should be temp or mem only */ 130 | case T_EXP: 131 | if (stm->u.EXP->kind == T_CALL) 132 | return seq(reorder(get_call_rlist(stm->u.EXP)), stm); 133 | else return seq(reorder(ExpRefList(&stm->u.EXP, NULL)), stm); 134 | default: 135 | return stm; 136 | } 137 | } 138 | 139 | /* linear gets rid of the top-level SEQ's, producing a list */ 140 | static T_stmList linear(T_stm stm, T_stmList right) 141 | { 142 | if (stm->kind == T_SEQ) 143 | return linear(stm->u.SEQ.left,linear(stm->u.SEQ.right,right)); 144 | else return T_StmList(stm, right); 145 | } 146 | 147 | /* From an arbitrary Tree statement, produce a list of cleaned trees 148 | satisfying the following properties: 149 | 1. No SEQ's or ESEQ's 150 | 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) */ 151 | T_stmList C_linearize(T_stm stm) 152 | { 153 | return linear(do_stm(stm), NULL); 154 | } 155 | 156 | static C_stmListList StmListList(T_stmList head, C_stmListList tail) 157 | {C_stmListList p = (C_stmListList) checked_malloc (sizeof *p); 158 | p->head=head; p->tail=tail; 159 | return p; 160 | } 161 | 162 | /* Go down a list looking for end of basic block */ 163 | static C_stmListList next(T_stmList prevstms, T_stmList stms, Temp_label done) 164 | { 165 | if (!stms) 166 | return next(prevstms, 167 | T_StmList(T_Jump(T_Name(done), Temp_LabelList(done, NULL)), 168 | NULL), done); 169 | if (stms->head->kind == T_JUMP || stms->head->kind == T_CJUMP) { 170 | C_stmListList stmLists; 171 | prevstms->tail = stms; 172 | stmLists = mkBlocks(stms->tail, done); 173 | stms->tail = NULL; 174 | return stmLists; 175 | } 176 | else if (stms->head->kind == T_LABEL) { 177 | Temp_label lab = stms->head->u.LABEL; 178 | return next(prevstms, T_StmList(T_Jump(T_Name(lab), Temp_LabelList(lab, NULL)), 179 | stms), done); 180 | } 181 | else { 182 | prevstms->tail = stms; 183 | return next(stms, stms->tail, done); 184 | } 185 | } 186 | 187 | /* Create the beginning of a basic block */ 188 | static C_stmListList mkBlocks(T_stmList stms, Temp_label done) 189 | { 190 | if (!stms) { 191 | return NULL; 192 | } 193 | if (stms->head->kind != T_LABEL) { 194 | return mkBlocks(T_StmList(T_Label(Temp_newlabel()), stms), done); 195 | } 196 | /* else there already is a label */ 197 | return StmListList(stms, next(stms, stms->tail, done)); 198 | } 199 | 200 | /* basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) 201 | From a list of cleaned trees, produce a list of 202 | basic blocks satisfying the following properties: 203 | 1. and 2. as above; 204 | 3. Every block begins with a LABEL; 205 | 4. A LABEL appears only at the beginning of a block; 206 | 5. Any JUMP or CJUMP is the last stm in a block; 207 | 6. Every block ends with a JUMP or CJUMP; 208 | Also produce the "label" to which control will be passed 209 | upon exit. 210 | */ 211 | struct C_block C_basicBlocks(T_stmList stmList) 212 | { 213 | struct C_block b; 214 | b.label = Temp_newlabel(); 215 | b.stmLists = mkBlocks(stmList, b.label); 216 | 217 | return b; 218 | } 219 | 220 | static S_table block_env; 221 | static struct C_block global_block; 222 | 223 | static T_stmList getLast(T_stmList list) 224 | { 225 | T_stmList last = list; 226 | while (last->tail->tail) last = last->tail; 227 | return last; 228 | } 229 | 230 | static void trace(T_stmList list) 231 | { 232 | T_stmList last = getLast(list); 233 | T_stm lab = list->head; 234 | T_stm s = last->tail->head; 235 | S_enter(block_env, lab->u.LABEL, NULL); 236 | if (s->kind == T_JUMP) { 237 | T_stmList target = (T_stmList) S_look(block_env, s->u.JUMP.jumps->head); 238 | if (!s->u.JUMP.jumps->tail && target) { 239 | last->tail = target; /* merge the 2 lists removing JUMP stm */ 240 | trace(target); 241 | } 242 | else last->tail->tail = getNext(); /* merge and keep JUMP stm */ 243 | } 244 | /* we want false label to follow CJUMP */ 245 | else if (s->kind == T_CJUMP) { 246 | T_stmList true = (T_stmList) S_look(block_env, s->u.CJUMP.true); 247 | T_stmList false = (T_stmList) S_look(block_env, s->u.CJUMP.false); 248 | if (false) { 249 | last->tail->tail = false; 250 | trace(false); 251 | } 252 | else if (true) { /* convert so that existing label is a false label */ 253 | last->tail->head = T_Cjump(T_notRel(s->u.CJUMP.op), s->u.CJUMP.left, 254 | s->u.CJUMP.right, s->u.CJUMP.false, 255 | s->u.CJUMP.true); 256 | last->tail->tail = true; 257 | trace(true); 258 | } 259 | else { 260 | Temp_label false = Temp_newlabel(); 261 | last->tail->head = T_Cjump(s->u.CJUMP.op, s->u.CJUMP.left, 262 | s->u.CJUMP.right, s->u.CJUMP.true, false); 263 | last->tail->tail = T_StmList(T_Label(false), getNext()); 264 | } 265 | } 266 | else assert(0); 267 | } 268 | 269 | /* get the next block from the list of stmLists, using only those that have 270 | * not been traced yet */ 271 | static T_stmList getNext() 272 | { 273 | if (!global_block.stmLists) 274 | return T_StmList(T_Label(global_block.label), NULL); 275 | else { 276 | T_stmList s = global_block.stmLists->head; 277 | if (S_look(block_env, s->head->u.LABEL)) {/* label exists in the table */ 278 | trace(s); 279 | return s; 280 | } 281 | else { 282 | global_block.stmLists = global_block.stmLists->tail; 283 | return getNext(); 284 | } 285 | } 286 | } 287 | /* traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list 288 | From a list of basic blocks satisfying properties 1-6, 289 | along with an "exit" label, 290 | produce a list of stms such that: 291 | 1. and 2. as above; 292 | 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. 293 | The blocks are reordered to satisfy property 7; also 294 | in this reordering as many JUMP(T.NAME(lab)) statements 295 | as possible are eliminated by falling through into T.LABEL(lab). 296 | */ 297 | T_stmList C_traceSchedule(struct C_block b) 298 | { C_stmListList sList; 299 | block_env = S_empty(); 300 | global_block = b; 301 | 302 | for (sList=global_block.stmLists; sList; sList=sList->tail) { 303 | S_enter(block_env, sList->head->head->u.LABEL, sList->head); 304 | } 305 | 306 | return getNext(); 307 | } 308 | 309 | -------------------------------------------------------------------------------- /chap9/canon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * canon.h - Definitions for canon.c which converts the IR trees into 3 | * basic blocks and traces. 4 | * 5 | */ 6 | typedef struct C_stmListList_ *C_stmListList; 7 | struct C_block { C_stmListList stmLists; Temp_label label;}; 8 | struct C_stmListList_ { T_stmList head; C_stmListList tail;}; 9 | 10 | T_stmList C_linearize(T_stm stm); 11 | /* From an arbitrary Tree statement, produce a list of cleaned trees 12 | satisfying the following properties: 13 | 1. No SEQ's or ESEQ's 14 | 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) 15 | */ 16 | 17 | struct C_block C_basicBlocks(T_stmList stmList); 18 | /* basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) 19 | From a list of cleaned trees, produce a list of 20 | basic blocks satisfying the following properties: 21 | 1. and 2. as above; 22 | 3. Every block begins with a LABEL; 23 | 4. A LABEL appears only at the beginning of a block; 24 | 5. Any JUMP or CJUMP is the last stm in a block; 25 | 6. Every block ends with a JUMP or CJUMP; 26 | Also produce the "label" to which control will be passed 27 | upon exit. 28 | */ 29 | 30 | T_stmList C_traceSchedule(struct C_block b); 31 | /* traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list 32 | From a list of basic blocks satisfying properties 1-6, 33 | along with an "exit" label, 34 | produce a list of stms such that: 35 | 1. and 2. as above; 36 | 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. 37 | The blocks are reordered to satisfy property 7; also 38 | in this reordering as many JUMP(T.NAME(lab)) statements 39 | as possible are eliminated by falling through into T.LABEL(lab). 40 | */ 41 | 42 | -------------------------------------------------------------------------------- /chap9/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | */ 4 | 5 | #include 6 | #include "util.h" 7 | #include "symbol.h" 8 | #include "absyn.h" 9 | #include "errormsg.h" 10 | #include "temp.h" /* needed by translate.h */ 11 | #include "tree.h" /* needed by frame.h */ 12 | #include "assem.h" 13 | #include "frame.h" /* needed by translate.h and printfrags prototype */ 14 | #include "semant.h" /* function prototype for transProg */ 15 | #include "canon.h" 16 | #include "prabsyn.h" 17 | #include "printtree.h" 18 | #include "escape.h" 19 | #include "parse.h" 20 | #include "codegen.h" 21 | 22 | extern bool anyErrors; 23 | 24 | /* print the assembly language instructions to filename.s */ 25 | static void doProc(FILE *out, F_frame frame, T_stm body) 26 | { 27 | AS_proc proc; 28 | struct RA_result allocation; 29 | T_stmList stmList; 30 | AS_instrList iList; 31 | 32 | stmList = C_linearize(body); 33 | stmList = C_traceSchedule(C_basicBlocks(stmList)); 34 | /* printStmList(stdout, stmList);*/ 35 | iList = F_codegen(frame, stmList); /* 9 */ 36 | 37 | fprintf(out, "BEGIN %s\n", Temp_labelstring(F_name(frame))); 38 | AS_printInstrList (out, iList, 39 | Temp_layerMap(F_tempMap,Temp_name())); 40 | fprintf(out, "END %s\n\n", Temp_labelstring(F_name(frame))); 41 | } 42 | 43 | int main(int argc, string *argv) 44 | { 45 | A_exp absyn_root; 46 | S_table base_env, base_tenv; 47 | F_fragList frags; 48 | char outfile[100]; 49 | FILE *out = stdout; 50 | 51 | if (argc==2) { 52 | absyn_root = parse(argv[1]); 53 | if (!absyn_root) 54 | return 1; 55 | 56 | #if 0 57 | pr_exp(out, absyn_root, 0); /* print absyn data structure */ 58 | fprintf(out, "\n"); 59 | #endif 60 | 61 | Esc_findEscape(absyn_root); /* set varDec's escape field */ 62 | 63 | frags = SEM_transProg(absyn_root); 64 | if (anyErrors) return 1; /* don't continue */ 65 | 66 | /* convert the filename */ 67 | sprintf(outfile, "%s.s", argv[1]); 68 | out = fopen(outfile, "w"); 69 | /* Chapter 8, 9, 10, 11 & 12 */ 70 | for (;frags;frags=frags->tail) 71 | if (frags->head->kind == F_procFrag) 72 | doProc(out, frags->head->u.proc.frame, frags->head->u.proc.body); 73 | else if (frags->head->kind == F_stringFrag) 74 | fprintf(out, "%s\n", frags->head->u.stringg.str); 75 | 76 | fclose(out); 77 | return 0; 78 | } 79 | EM_error(0,"usage: tiger file.tig"); 80 | return 1; 81 | } 82 | -------------------------------------------------------------------------------- /testcases/merge.tig: -------------------------------------------------------------------------------- 1 | let 2 | 3 | type any = {any : int} 4 | var buffer := getchar() 5 | 6 | function readint(any: any) : int = 7 | let var i := 0 8 | function isdigit(s : string) : int = 9 | ord(buffer)>=ord("0") & ord(buffer)<=ord("9") 10 | function skipto() = 11 | while buffer=" " | buffer="\n" 12 | do buffer := getchar() 13 | in skipto(); 14 | any.any := isdigit(buffer); 15 | while isdigit(buffer) 16 | do (i := i*10+ord(buffer)-ord("0"); buffer := getchar()); 17 | i 18 | end 19 | 20 | type list = {first: int, rest: list} 21 | 22 | function readlist() : list = 23 | let var any := any{any=0} 24 | var i := readint(any) 25 | in if any.any 26 | then list{first=i,rest=readlist()} 27 | else nil 28 | end 29 | 30 | function merge(a: list, b: list) : list = 31 | if a=nil then b 32 | else if b=nil then a 33 | else if a.first < b.first 34 | then list{first=a.first,rest=merge(a.rest,b)} 35 | else list{first=b.first,rest=merge(a,b.rest)} 36 | 37 | function printint(i: int) = 38 | let function f(i:int) = if i>0 39 | then (f(i/10); print(chr(i-i/10*10+ord("0")))) 40 | in if i<0 then (print("-"); f(-i)) 41 | else if i>0 then f(i) 42 | else print("0") 43 | end 44 | 45 | function printlist(l: list) = 46 | if l=nil then print("\n") 47 | else (printint(l.first); print(" "); printlist(l.rest)) 48 | 49 | var list1 := readlist() 50 | var list2 := (buffer:=getchar(); readlist()) 51 | 52 | 53 | /* BODY OF MAIN PROGRAM */ 54 | in printlist(merge(list1,list2)) 55 | end 56 | 57 | -------------------------------------------------------------------------------- /testcases/queens.tig: -------------------------------------------------------------------------------- 1 | /* A program to solve the 8-queens problem */ 2 | 3 | let 4 | var N := 8 5 | 6 | type intArray = array of int 7 | 8 | var row := intArray [ N ] of 0 9 | var col := intArray [ N ] of 0 10 | var diag1 := intArray [N+N-1] of 0 11 | var diag2 := intArray [N+N-1] of 0 12 | 13 | function printboard() = 14 | (for i := 0 to N-1 15 | do (for j := 0 to N-1 16 | do print(if col[i]=j then " O" else " ."); 17 | print("\n")); 18 | print("\n")) 19 | 20 | function try(c:int) = 21 | ( /* for i:= 0 to c do print("."); print("\n"); flush();*/ 22 | if c=N 23 | then printboard() 24 | else for r := 0 to N-1 25 | do if row[r]=0 & diag1[r+c]=0 & diag2[r+7-c]=0 26 | then (row[r]:=1; diag1[r+c]:=1; diag2[r+7-c]:=1; 27 | col[c]:=r; 28 | try(c+1); 29 | row[r]:=0; diag1[r+c]:=0; diag2[r+7-c]:=0) 30 | 31 | ) 32 | in try(0) 33 | end 34 | -------------------------------------------------------------------------------- /testcases/test1.tig: -------------------------------------------------------------------------------- 1 | /* an array type and an array variable */ 2 | let 3 | type arrtype = array of int 4 | var arr1:arrtype := arrtype [10] of 0 5 | in 6 | arr1 7 | end 8 | -------------------------------------------------------------------------------- /testcases/test10.tig: -------------------------------------------------------------------------------- 1 | /* error : body of while not unit */ 2 | while(10 > 5) do 5+6 3 | -------------------------------------------------------------------------------- /testcases/test11.tig: -------------------------------------------------------------------------------- 1 | /* error hi expr is not int, and index variable erroneously assigned to. */ 2 | for i:=10 to " " do 3 | i := i - 1 4 | -------------------------------------------------------------------------------- /testcases/test12.tig: -------------------------------------------------------------------------------- 1 | /* valid for and let */ 2 | 3 | let 4 | var a:= 0 5 | in 6 | for i:=0 to 100 do (a:=a+1;()) 7 | end 8 | -------------------------------------------------------------------------------- /testcases/test13.tig: -------------------------------------------------------------------------------- 1 | /* error: comparison of incompatible types */ 2 | 3 | 3 > "df" 4 | -------------------------------------------------------------------------------- /testcases/test14.tig: -------------------------------------------------------------------------------- 1 | /* error : compare rec with array */ 2 | 3 | let 4 | 5 | type arrtype = array of int 6 | type rectype = {name:string, id: int} 7 | 8 | var rec := rectype {name="aname", id=0} 9 | var arr := arrtype [3] of 0 10 | 11 | in 12 | if rec <> arr then 3 else 4 13 | end 14 | -------------------------------------------------------------------------------- /testcases/test15.tig: -------------------------------------------------------------------------------- 1 | /* error : if-then returns non unit */ 2 | 3 | if 20 then 3 4 | -------------------------------------------------------------------------------- /testcases/test16.tig: -------------------------------------------------------------------------------- 1 | /* error: mutually recursive types thet do not pass through record or array */ 2 | let 3 | 4 | type a=c 5 | type b=a 6 | type c=d 7 | type d=a 8 | 9 | in 10 | "" 11 | end 12 | -------------------------------------------------------------------------------- /testcases/test17.tig: -------------------------------------------------------------------------------- 1 | /* error: definition of recursive types is interrupted */ 2 | let 3 | /* define a tree */ 4 | type tree ={key: int, children: treelist} 5 | var d:int :=0 6 | type treelist = {hd: tree, tl: treelist} 7 | 8 | in 9 | d 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test18.tig: -------------------------------------------------------------------------------- 1 | /* error : definition of recursive functions is interrupted */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | var d:=0 8 | 9 | function do_nothing2(d: int):string = 10 | (do_nothing1(d, "str");" ") 11 | 12 | in 13 | do_nothing1(0, "str2") 14 | end 15 | 16 | -------------------------------------------------------------------------------- /testcases/test19.tig: -------------------------------------------------------------------------------- 1 | /* error : second function uses variables local to the first one, undeclared variable */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | function do_nothing2(d: int):string = 8 | (do_nothing1(a, "str");" ") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test2.tig: -------------------------------------------------------------------------------- 1 | /* arr1 is valid since expression 0 is int = myint */ 2 | let 3 | type myint = int 4 | type arrtype = array of myint 5 | 6 | var arr1:arrtype := arrtype [10] of 0 7 | in 8 | arr1 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test20.tig: -------------------------------------------------------------------------------- 1 | /* error: undeclared variable i */ 2 | 3 | while 10 > 5 do (i+1;()) 4 | -------------------------------------------------------------------------------- /testcases/test21.tig: -------------------------------------------------------------------------------- 1 | /* error : procedure returns value and procedure is used in arexpr */ 2 | let 3 | 4 | /* calculate n! */ 5 | function nfactor(n: int) = 6 | if n = 0 7 | then 1 8 | else n * nfactor(n-1) 9 | 10 | in 11 | nfactor(10) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test22.tig: -------------------------------------------------------------------------------- 1 | /* error : field not in record type */ 2 | 3 | let 4 | type rectype = {name:string , id:int} 5 | var rec1 := rectype {name="Name", id=0} 6 | in 7 | rec1.nam := "asd" 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test23.tig: -------------------------------------------------------------------------------- 1 | /* error : type mismatch */ 2 | 3 | let 4 | type rectype = {name:string , id:int} 5 | var rec1 := rectype {name="aname", id=0} 6 | in 7 | rec1.name := 3; 8 | rec1.id := "" 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test24.tig: -------------------------------------------------------------------------------- 1 | /* error : variable not array */ 2 | let 3 | var d:=0 4 | in 5 | d[3] 6 | end 7 | 8 | -------------------------------------------------------------------------------- /testcases/test25.tig: -------------------------------------------------------------------------------- 1 | /* error : variable not record */ 2 | let 3 | var d:=0 4 | in 5 | d.f 6 | end 7 | 8 | -------------------------------------------------------------------------------- /testcases/test26.tig: -------------------------------------------------------------------------------- 1 | /* error : integer required */ 2 | 3 | 3 + "var" 4 | -------------------------------------------------------------------------------- /testcases/test27.tig: -------------------------------------------------------------------------------- 1 | /* locals hide globals */ 2 | let 3 | var a:=0 4 | 5 | function g(a:int):int = a 6 | in 7 | g(2) 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test28.tig: -------------------------------------------------------------------------------- 1 | /* error : different record types */ 2 | 3 | let 4 | type rectype1 = {name:string , id:int} 5 | type rectype2 = {name:string , id:int} 6 | 7 | var rec1: rectype1 := rectype2 {name="Name", id=0} 8 | in 9 | rec1 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test29.tig: -------------------------------------------------------------------------------- 1 | /* error : different array types */ 2 | 3 | let 4 | type arrtype1 = array of int 5 | type arrtype2 = array of int 6 | 7 | var arr1: arrtype1 := arrtype2 [10] of 0 8 | in 9 | arr1 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test3.tig: -------------------------------------------------------------------------------- 1 | /* a record type and a record variable */ 2 | let 3 | type rectype = {name:string, age:int} 4 | var rec1:rectype := rectype {name="Nobody", age=1000} 5 | in 6 | rec1.name := "Somebody"; 7 | rec1 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test30.tig: -------------------------------------------------------------------------------- 1 | /* synonyms are fine */ 2 | 3 | let 4 | type a = array of int 5 | type b = a 6 | 7 | var arr1:a := b [10] of 0 8 | in 9 | arr1[2] 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test31.tig: -------------------------------------------------------------------------------- 1 | /* error : type constraint and init value differ */ 2 | let 3 | var a:int := " " 4 | in 5 | a 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test32.tig: -------------------------------------------------------------------------------- 1 | /* error : initializing exp and array type differ */ 2 | 3 | let 4 | type arrayty = array of int 5 | 6 | var a := arrayty [10] of " " 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test33.tig: -------------------------------------------------------------------------------- 1 | /* error : unknown type */ 2 | let 3 | var a:= rectype {} 4 | in 5 | 0 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test34.tig: -------------------------------------------------------------------------------- 1 | /* error : formals and actuals have different types */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g("one", "two") 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test35.tig: -------------------------------------------------------------------------------- 1 | /* error : formals are more then actuals */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g("one") 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test36.tig: -------------------------------------------------------------------------------- 1 | /* error : formals are fewer then actuals */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g(3,"one",5) 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test37.tig: -------------------------------------------------------------------------------- 1 | /* redeclaration of variable; this is legal, there are two different 2 | variables with the same name. The second one hides the first. */ 3 | let 4 | var a := 0 5 | var a := " " 6 | in 7 | 0 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test38.tig: -------------------------------------------------------------------------------- 1 | /* This is illegal, since there are two types with the same name 2 | in the same (consecutive) batch of mutually recursive types. 3 | See also test47 */ 4 | let 5 | type a = int 6 | type a = string 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test39.tig: -------------------------------------------------------------------------------- 1 | /* This is illegal, since there are two functions with the same name 2 | in the same (consecutive) batch of mutually recursive functions. 3 | See also test48 */ 4 | let 5 | function g(a:int):int = a 6 | function g(a:int):int = a 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test4.tig: -------------------------------------------------------------------------------- 1 | /* define a recursive function */ 2 | let 3 | 4 | /* calculate n! */ 5 | function nfactor(n: int): int = 6 | if n = 0 7 | then 1 8 | else n * nfactor(n-1) 9 | 10 | in 11 | nfactor(10) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test40.tig: -------------------------------------------------------------------------------- 1 | /* error : procedure returns value */ 2 | let 3 | function g(a:int) = a 4 | in 5 | g(2) 6 | end 7 | 8 | -------------------------------------------------------------------------------- /testcases/test41.tig: -------------------------------------------------------------------------------- 1 | /* local types hide global */ 2 | let 3 | type a = int 4 | in 5 | let 6 | type a = string 7 | in 8 | 0 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test42.tig: -------------------------------------------------------------------------------- 1 | /* correct declarations */ 2 | let 3 | 4 | type arrtype1 = array of int 5 | type rectype1 = {name:string, address:string, id: int , age: int} 6 | type arrtype2 = array of rectype1 7 | type rectype2 = {name : string, dates: arrtype1} 8 | 9 | type arrtype3 = array of string 10 | 11 | var arr1 := arrtype1 [10] of 0 12 | var arr2 := arrtype2 [5] of rectype1 {name="aname", address="somewhere", id=0, age=0} 13 | var arr3:arrtype3 := arrtype3 [100] of "" 14 | 15 | var rec1 := rectype1 {name="Kapoios", address="Kapou", id=02432, age=44} 16 | var rec2 := rectype2 {name="Allos", dates= arrtype1 [3] of 1900} 17 | 18 | in 19 | 20 | arr1[0] := 1; 21 | arr1[9] := 3; 22 | arr2[3].name := "kati"; 23 | arr2[1].age := 23; 24 | arr3[34] := "sfd"; 25 | 26 | rec1.name := "sdf"; 27 | rec2.dates[0] := 2323; 28 | rec2.dates[2] := 2323 29 | 30 | end 31 | -------------------------------------------------------------------------------- /testcases/test43.tig: -------------------------------------------------------------------------------- 1 | /* initialize with unit and causing type mismatch in addition */ 2 | 3 | let 4 | var a := () 5 | in 6 | a + 3 7 | end 8 | -------------------------------------------------------------------------------- /testcases/test44.tig: -------------------------------------------------------------------------------- 1 | /* valid nil initialization and assignment */ 2 | let 3 | 4 | type rectype = {name:string, id:int} 5 | var b:rectype := nil 6 | 7 | in 8 | 9 | b := nil 10 | 11 | end 12 | -------------------------------------------------------------------------------- /testcases/test45.tig: -------------------------------------------------------------------------------- 1 | /* error: initializing nil expressions not constrained by record type */ 2 | let 3 | type rectype = {name:string, id:int} 4 | 5 | var a:= nil 6 | in 7 | a 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test46.tig: -------------------------------------------------------------------------------- 1 | /* valid rec comparisons */ 2 | let 3 | type rectype = {name:string, id:int} 4 | var b:rectype := nil 5 | in 6 | b = nil; 7 | b <> nil 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test47.tig: -------------------------------------------------------------------------------- 1 | /* This is legal. The second type "a" simply hides the first one. 2 | Because of the intervening variable declaration, the two "a" types 3 | are not in the same batch of mutually recursive types. 4 | See also test38 */ 5 | let 6 | type a = int 7 | var b := 4 8 | type a = string 9 | in 10 | 0 11 | end 12 | -------------------------------------------------------------------------------- /testcases/test48.tig: -------------------------------------------------------------------------------- 1 | /* This is legal. The second function "g" simply hides the first one. 2 | Because of the intervening variable declaration, the two "g" functions 3 | are not in the same batch of mutually recursive functions. 4 | See also test39 */ 5 | let 6 | function g(a:int):int = a 7 | type t = int 8 | function g(a:int):int = a 9 | in 10 | 0 11 | end 12 | -------------------------------------------------------------------------------- /testcases/test49.tig: -------------------------------------------------------------------------------- 1 | /* error: syntax error, nil should not be preceded by type-id. */ 2 | let 3 | type rectype = {name:string, id:int} 4 | 5 | var a:= rectype nil 6 | in 7 | a 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test5.tig: -------------------------------------------------------------------------------- 1 | /* define valid recursive types */ 2 | let 3 | /* define a list */ 4 | type intlist = {hd: int, tl: intlist} 5 | 6 | /* define a tree */ 7 | type tree ={key: int, children: treelist} 8 | type treelist = {hd: tree, tl: treelist} 9 | 10 | var lis:intlist := intlist { hd=0, tl= nil } 11 | 12 | in 13 | lis 14 | end 15 | -------------------------------------------------------------------------------- /testcases/test6.tig: -------------------------------------------------------------------------------- 1 | /* define valid mutually recursive procedures */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string)= 5 | do_nothing2(a+1) 6 | 7 | function do_nothing2(d: int) = 8 | do_nothing1(d, "str") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test7.tig: -------------------------------------------------------------------------------- 1 | /* define valid mutually recursive functions */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | function do_nothing2(d: int):string = 8 | (do_nothing1(d, "str");" ") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test8.tig: -------------------------------------------------------------------------------- 1 | /* correct if */ 2 | if (10 > 20) then 30 else 40 3 | -------------------------------------------------------------------------------- /testcases/test9.tig: -------------------------------------------------------------------------------- 1 | /* error : types of then - else differ */ 2 | 3 | if (5>4) then 13 else " " 4 | --------------------------------------------------------------------------------