├── LICENSE ├── README.md ├── ch11 ├── Op.icn ├── Op.java ├── hello.j0 ├── hello.java ├── j0machine.icn ├── j0machine.java ├── j0x.icn ├── j0x.java ├── makefile └── writehello.icn ├── ch12 ├── Op.icn ├── Op.java ├── address.icn ├── address.java ├── arraytype.java ├── byc.icn ├── byc.java ├── classtype.java ├── hello.icn ├── hello.j0 ├── hello.java ├── j0.icn ├── j0.java ├── j0gram.y ├── j0machine.icn ├── j0machine.java ├── j0x.icn ├── j0x.java ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.java ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── tac.icn ├── tac.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── typeinfo.icn ├── typeinfo.java ├── yyerror.icn └── yyerror.java ├── ch13 ├── Op.icn ├── Op.java ├── RegUse.java ├── address.icn ├── address.java ├── arraytype.java ├── byc.icn ├── byc.java ├── classtype.java ├── hello.java ├── j0.icn ├── j0.java ├── j0gram.y ├── j0machine.icn ├── j0machine.java ├── j0x.icn ├── j0x.java ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.java ├── reguse.icn ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── tac.icn ├── tac.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── typeinfo.icn ├── typeinfo.java ├── x64.icn ├── x64.java ├── x64loc.icn ├── x64loc.java ├── yyerror.icn └── yyerror.java ├── ch3 ├── dorrie.in ├── dorrie2.in ├── hello.java ├── j0.icn ├── j0.java ├── j0go.icn ├── j0go.java ├── javalex.l ├── nnws-tok.l ├── nnws.l ├── parser.java ├── simple.icn ├── simple.java ├── simple2.icn ├── simple2.java └── token.java ├── ch4 ├── Parser.java ├── Yylex.java ├── dorrie3.in ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0go.icn ├── j0go.java ├── j0gram.icn ├── j0gram.y ├── j0gram_tab.icn ├── javalex.icn ├── javalex.l ├── jzero.java ├── lexer.java ├── nameseq.y ├── nnws.l ├── ns.icn ├── ns.y ├── ns_tab.icn ├── parserTokens.java ├── parserVal.java ├── token.java ├── trivial.icn ├── trivial.java ├── yyerror.icn └── yyerror.java ├── ch5 ├── Yylex.java ├── cereal.icn ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.icn ├── j0gram.y ├── j0gram_tab.icn ├── javalex.icn ├── javalex.l ├── makefile ├── parser.java ├── parserVal.java ├── prodrule.java ├── serial.icn ├── serial.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── xy5.java ├── yyerror.icn └── yyerror.java ├── ch6 ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.y ├── javalex.l ├── makefile ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── xy5.java ├── yyerror.icn └── yyerror.java ├── ch7 ├── Yylex.java ├── arraytype.java ├── classtype.java ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.icn ├── j0gram.y ├── j0gram_tab.icn ├── javalex.icn ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.java ├── parserVal.java ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── typeinfo.icn ├── typeinfo.java ├── xy5.java ├── yyerror.icn └── yyerror.java ├── ch8 ├── arraytype.java ├── arrtst.java ├── classtype.java ├── clstest.java ├── funtest.java ├── hello.java ├── j0.icn ├── j0.java ├── j0gram.y ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.java ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── typeinfo.icn ├── typeinfo.java ├── xy5.java ├── yyerror.icn └── yyerror.java └── ch9 ├── Yylex.java ├── address.icn ├── address.java ├── arraytype.java ├── arrtst.java ├── classtype.java ├── clstest.java ├── funtest.java ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.icn ├── j0gram.y ├── j0gram_tab.icn ├── javalex.icn ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.java ├── parser.java ├── parserVal.java ├── serial.icn ├── serial.java ├── symtab.icn ├── symtab.java ├── symtab_entry.icn ├── symtab_entry.java ├── tac.icn ├── tac.java ├── token.icn ├── token.java ├── tree.icn ├── tree.java ├── typeinfo.icn ├── typeinfo.java ├── xy5.java ├── yyerror.icn └── yyerror.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ch11/Op.icn: -------------------------------------------------------------------------------- 1 | class Op(HALT, NOOP, ADD, SUB, MUL, DIV, MOD, NEG, PUSH, POP, CALL, RETURN, GOTO, BIF, 2 | LT, LE, GT, GE, EQ, NEQ, LOCAL, LOAD, STORE, R_NONE, R_ABS, R_IMM, R_STACK, R_HEAP) 3 | initially 4 | HALT := 1; NOOP := 2; ADD := 3; SUB := 4; MUL := 5 5 | DIV := 6; MOD := 7; NEG := 8; PUSH := 9; POP := 10 6 | CALL := 11; RETURN := 12; GOTO := 13; BIF := 14; LT := 15 7 | LE := 16; GT := 17; GE := 18; EQ := 19; NEQ := 20; 8 | LOCAL := 21; LOAD := 22; STORE := 23 9 | R_NONE := 0; R_ABS := 1; R_IMM := 2 10 | R_STACK := 3; R_HEAP := 4 11 | Op := self 12 | end 13 | 14 | procedure OpStr(i) 15 | if type(Op)~=="Op__state" then Op() 16 | case i of { 17 | Op.HALT: return "HALT" 18 | Op.NOOP: return "NOOP" 19 | Op.ADD: return "ADD" 20 | Op.SUB: return "SUB" 21 | Op.MUL: return "MUL" 22 | Op.DIV: return "DIV" 23 | Op.MOD: return "MOD" 24 | Op.NEG: return "NEG" 25 | Op.PUSH: return "PUSH" 26 | Op.POP: return "POP" 27 | Op.CALL: return "CALL" 28 | Op.RETURN: return "RETURN" 29 | Op.GOTO: return "GOTO" 30 | Op.BIF: return "BIF" 31 | Op.LT: return "LT" 32 | Op.LE: return "LE" 33 | Op.GT: return "GT" 34 | Op.GE: return "GE" 35 | Op.EQ: return "EQ" 36 | Op.NEQ: return "NEQ" 37 | Op.LOCAL: return "LOCAL" 38 | Op.LOAD: return "LOAD" 39 | Op.STORE: return "STORE" 40 | default: return "(unknown:"||image(i)||")" 41 | } 42 | end 43 | 44 | procedure OpRStr(opr) 45 | if type(Op)~=="Op__state" then Op() 46 | case opr of { 47 | Op.R_NONE: return "NONE" 48 | Op.R_ABS: return "ABS" 49 | Op.R_IMM: return "IMM" 50 | Op.R_STACK: return "STACK" 51 | Op.R_HEAP: return "HEAP" 52 | } 53 | end 54 | -------------------------------------------------------------------------------- /ch11/Op.java: -------------------------------------------------------------------------------- 1 | public class Op { 2 | public final static short HALT=1, NOOP=2, ADD=3, SUB=4, 3 | MUL=5, DIV=6, MOD=7, NEG=8, PUSH=9, POP=10, CALL=11, 4 | RETURN=12, GOTO=13, BIF=14, LT=15, LE=16, GT=17, GE=18, 5 | EQ=19, NEQ=20, LOCAL=21, LOAD=22, STORE=23; 6 | public final static short R_NONE=0, R_ABS=1, R_IMM=2, 7 | R_STACK=3, R_HEAP=4; 8 | } 9 | -------------------------------------------------------------------------------- /ch11/hello.j0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Build-Your-Own-Programming-Language/714a2367238d52144843a871b68f908fdee5f5b2/ch11/hello.j0 -------------------------------------------------------------------------------- /ch11/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | int x = argv.length; 4 | x = x + 2; 5 | if (x > 3) { 6 | System.out.println("hello, jzero!"); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch11/j0x.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | if not (filename := argv[1]) then 3 | stop("usage: j0x file[.j0]") 4 | if not (filename[-3:0] == ".j0") then argv[1] ||:= ".j0" 5 | j0machine := j0machine() 6 | j0machine.init(filename) 7 | j0machine.interp() 8 | end 9 | -------------------------------------------------------------------------------- /ch11/j0x.java: -------------------------------------------------------------------------------- 1 | public class j0x { 2 | public static void main(String[] argv) { 3 | if (argv.length < 1) { 4 | System.err.println("usage: j0x file[.j0]" + argv.length); 5 | System.exit(1); 6 | } 7 | String filename = argv[0]; 8 | if (! filename.endsWith(".j0")) 9 | filename = filename + ".j0"; 10 | try { 11 | j0machine.init(filename); 12 | } catch(Exception ex) { 13 | System.err.println("Can't initialize. Exiting."); 14 | System.exit(1); 15 | } 16 | j0machine.interp(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch11/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | U=j0x.u j0machine.u op.u 5 | unicon:j0x 6 | %.u : %.icn 7 | unicon -c $< 8 | 9 | j0x: $(U) 10 | unicon $(U) 11 | 12 | JSRC=j0x.java j0machine.java Op.java 13 | java: j0x.class 14 | 15 | j0x.class: $(JSRC) 16 | javac $(JSRC) 17 | -------------------------------------------------------------------------------- /ch11/writehello.icn: -------------------------------------------------------------------------------- 1 | procedure main() 2 | f := open("hello.j0","w") | stop("can't open hello.j0") 3 | writes(f, "Jzero!!\0") # word 0, magic word 4 | writes(f, "1.0\0\0\0\0\0") # word 1, version # 5 | writes(f, "\0\0\4\0\0\0\0\0") # word 2, first instruction at word 4 6 | writes(f, "hello\0\0\0") # word 3, static data 7 | writes(f, "\11\2\70\0\0\0\0\0") # word 4, PUSH IMM 56, func entry pt 56 8 | writes(f, "\13\2\0\0\0\0\0\0") # word 5, call 0 9 | writes(f, "\1\0\0\0\0\0\0\0") # word 6, halt 10 | writes(f, "\11\2\377\377\377\377\377\377") # word 7, push IMM -1 11 | writes(f, "\11\2\30\0\0\0\0\0") # word 8, push IMM 24 "hello" 12 | writes(f, "\13\2\1\0\0\0\0\0") # word 9, call IMM 1 13 | writes(f, "\14\2\0\0\0\0\0\0") # word 10, ret IMM 0 14 | close(f) 15 | end 16 | -------------------------------------------------------------------------------- /ch12/Op.icn: -------------------------------------------------------------------------------- 1 | class Op(HALT, NOOP, ADD, SUB, MUL, DIV, MOD, NEG, PUSH, POP, CALL, RETURN, 2 | GOTO, BIF, LT, LE, GT, GE, EQ, NEQ, LOCAL, LOAD, STORE, 3 | LABEL, STRING, CODE, PROC, GLOBAL, END, 4 | R_NONE, R_ABS, R_IMM, R_STACK, R_HEAP) 5 | initially 6 | HALT := 1; NOOP := 2; ADD := 3; SUB := 4; MUL := 5 7 | DIV := 6; MOD := 7; NEG := 8; PUSH := 9; POP := 10 8 | CALL := 11; RETURN := 12; GOTO := 13; BIF := 14; LT := 15 9 | LE := 16; GT := 17; GE := 18; EQ := 19; NEQ := 20; 10 | LOCAL := 21; LOAD := 22; STORE := 23; 11 | LABEL := 101; STRING:=102; CODE:=103; PROC:=104; GLOBAL := 105; END := 106 12 | R_NONE := 0; R_ABS := 1; R_IMM := 2 13 | R_STACK := 3; R_HEAP := 4 14 | Op := self 15 | end 16 | 17 | procedure OpStr(i) 18 | if type(Op)~=="Op__state" then Op() 19 | case i of { 20 | Op.HALT: return "HALT" 21 | Op.NOOP: return "NOOP" 22 | Op.ADD: return "ADD" 23 | Op.SUB: return "SUB" 24 | Op.MUL: return "MUL" 25 | Op.DIV: return "DIV" 26 | Op.MOD: return "MOD" 27 | Op.NEG: return "NEG" 28 | Op.PUSH: return "PUSH" 29 | Op.POP: return "POP" 30 | Op.CALL: return "CALL" 31 | Op.RETURN: return "RETURN" 32 | Op.GOTO: return "GOTO" 33 | Op.BIF: return "BIF" 34 | Op.LT: return "LT" 35 | Op.LE: return "LE" 36 | Op.GT: return "GT" 37 | Op.GE: return "GE" 38 | Op.EQ: return "EQ" 39 | Op.NEQ: return "NEQ" 40 | Op.LOCAL: return "LOCAL" 41 | Op.LOAD: return "LOAD" 42 | Op.STORE: return "STORE" 43 | default: return "(unknown:"||image(i)||")" 44 | } 45 | end 46 | 47 | procedure OpRStr(opr) 48 | if type(Op)~=="Op__state" then Op() 49 | case opr of { 50 | Op.R_NONE: return "NONE" 51 | Op.R_ABS: return "ABS" 52 | Op.R_IMM: return "IMM" 53 | Op.R_STACK: return "STACK" 54 | Op.R_HEAP: return "HEAP" 55 | } 56 | end 57 | -------------------------------------------------------------------------------- /ch12/Op.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class Op { 3 | public final static short HALT=1, NOOP=2, ADD=3, SUB=4, 4 | MUL=5, DIV=6, MOD=7, NEG=8, PUSH=9, POP=10, CALL=11, 5 | RETURN=12, GOTO=13, BIF=14, LT=15, LE=16, GT=17, GE=18, 6 | EQ=19, NEQ=20, LOCAL=21, LOAD=22, STORE=23; 7 | public final static short LABEL=101, STRING=102, 8 | CODE=103, PROC=104, GLOBAL=105, END=106; 9 | public final static short R_NONE=0, R_ABS=1, R_IMM=2, R_STACK=3, R_HEAP=4; 10 | } 11 | -------------------------------------------------------------------------------- /ch12/address.icn: -------------------------------------------------------------------------------- 1 | class address(region, offset) 2 | method regaddr() 3 | return if region == "method" then "loc" else region 4 | end 5 | method str() 6 | if region=="lab" then return "L"||offset 7 | return regaddr() || ":" || offset 8 | end 9 | method print() 10 | writes(str()) 11 | end 12 | #initially 13 | # if /region then { 14 | #write("when is it ever OK to make an address with no region?") 15 | #runerr(103, region) 16 | # } 17 | end 18 | -------------------------------------------------------------------------------- /ch12/address.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class address { 3 | public String region; 4 | public int offset; 5 | public String regaddr() { return region.equals("method")?"loc":region; } 6 | public String str() { 7 | if (region.equals("lab")) return "L"+offset; 8 | return regaddr() + ":" + offset; } 9 | public void print() { System.out.print(str()); } 10 | address(String s, int o) { region = s; offset = o; } 11 | } 12 | -------------------------------------------------------------------------------- /ch12/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class arraytype extends typeinfo { 3 | typeinfo element_type; 4 | public String str() { 5 | return "array of " + (element_type!=null?element_type.str():"undef"); 6 | } 7 | public arraytype(typeinfo t) { 8 | basetype = "array"; element_type = t; } 9 | } 10 | -------------------------------------------------------------------------------- /ch12/byc.icn: -------------------------------------------------------------------------------- 1 | link printf 2 | class byc(op, opreg, opnd) 3 | method print(f:&output) 4 | write(f, "\t", nameof(), " ", addrof()) | 5 | write(&errout, "can't print ", image(self), " op ", image(op)) 6 | end 7 | method nameof() 8 | static opnames 9 | initial opnames := table(Op.HALT, "halt", Op.NOOP, "noop", 10 | Op.ADD, "add", Op.SUB, "sub", Op.MUL, "mul", 11 | Op.DIV, "div", Op.MOD, "mod", Op.NEG, "neg", 12 | Op.PUSH, "push", Op.POP, "pop", Op.CALL, "call", 13 | Op.RETURN, "return", Op.GOTO, "goto", Op.BIF, "bif", 14 | Op.LT, "lt", Op.LE, "le", Op.GT, "gt", Op.GE, "ge", 15 | Op.EQ, "eq", Op.NEQ, "neq", Op.LOCAL, "local", 16 | Op.LOAD, "load", Op.STORE, "store", Op.LABEL, "LABEL", 17 | Op.STRING, "STRING", Op.CODE, "CODE", Op.PROC, "PROC", 18 | Op.GLOBAL, "GLOBAL", Op.END, "END") 19 | return opnames[op] 20 | end 21 | method addrof() 22 | case opreg of { 23 | Op.R_NONE | &null: return "" 24 | Op.R_ABS: return "@" || sprintf("%x",opnd) 25 | Op.R_IMM: return string(opnd) 26 | Op.R_STACK: return "stack:" || opnd 27 | Op.R_HEAP: return "heap:" || opnd 28 | default: { 29 | return string(opreg) || ":" || opnd 30 | } 31 | } 32 | end 33 | 34 | method printb(f:&output) 35 | writes(f, char(op), char(\opreg|0)) 36 | x := (\opnd | 0) 37 | every !6 do { 38 | writes(f, char(iand(x, 255))) 39 | x := ishift(x, -8) 40 | } 41 | end 42 | method addr(a) 43 | if /a then opreg := Op.R_NONE 44 | else if type(a) == "integer" then { 45 | opreg := Op.R_IMM; opnd := a 46 | } 47 | else if type(a) == "string" then { 48 | if not (sa := stringtab.lookup(a)) then write("don't know ", image(a)) 49 | # string region addresses are just pointers offset 24 from start 50 | opreg := Op.R_IMM; opnd := sa.addr.offset + 24 51 | } 52 | else case a.region of { 53 | "method": { opreg := Op.R_STACK; opnd := a.offset } 54 | "global": { opreg := Op.R_ABS; opnd := a.offset + stringtab.count } 55 | "const": { opreg := Op.R_ABS; opnd := a.offset } 56 | "lab": { opreg := Op.R_ABS; opnd := a.offset } 57 | "obj": { opreg := Op.R_HEAP; opnd := a.offset } 58 | "imm": { opreg := Op.R_IMM; opnd := a.offset } 59 | "strings": { opreg := Op.R_IMM; opnd := a.offset + 24 } 60 | default: { 61 | write("system error. region ", image(a.region), 62 | " offset ", image(a.offset)) 63 | runerr(103, a.region) 64 | } 65 | } 66 | end 67 | initially(o, a) 68 | op := o; addr(a); 69 | if type(nameof()) ~== "string" then { 70 | write(&errout, "bad op ", image(op)) 71 | runerr(103, op) 72 | } 73 | end 74 | -------------------------------------------------------------------------------- /ch12/byc.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | import java.util.HashMap; 3 | import java.io.PrintStream; 4 | public class byc { 5 | int op, opreg; 6 | long opnd; 7 | public byc(int o, address a) { 8 | op=o; addr(a); 9 | } 10 | public void print(PrintStream f) { 11 | f.println("\t" + nameof() + " " + addrof()); 12 | } 13 | public void print() { 14 | print(System.out); 15 | } 16 | static HashMap ops; 17 | static { ops = new HashMap<>(); 18 | ops.put(Op.HALT,"halt"); ops.put(Op.NOOP,"noop"); 19 | ops.put(Op.ADD,"add"); ops.put(Op.SUB,"sub"); 20 | ops.put(Op.MUL,"mul"); ops.put(Op.DIV, "div"); 21 | ops.put(Op.MOD,"mod"); ops.put(Op.NEG, "neg"); 22 | ops.put(Op.PUSH,"push"); ops.put(Op.POP, "pop"); 23 | ops.put(Op.CALL, "call"); ops.put(Op.RETURN, "return"); 24 | ops.put(Op.GOTO, "goto"); ops.put(Op.BIF, "bif"); 25 | ops.put(Op.LT, "lt"); ops.put(Op.LE, "le"); 26 | ops.put(Op.GT, "gt"); ops.put(Op.GE, "ge"); 27 | ops.put(Op.EQ, "eq"); ops.put(Op.NEQ, "neq"); 28 | ops.put(Op.LOCAL, "local"); ops.put(Op.LOAD, "load"); 29 | ops.put(Op.STORE, "store"); ops.put(Op.LABEL, "LABEL"); 30 | ops.put(Op.STRING, "STRING"); ops.put(Op.CODE, "CODE"); 31 | ops.put(Op.PROC, "PROC"); ops.put(Op.GLOBAL, "GLOBAL"); 32 | ops.put(Op.END, "END"); 33 | } 34 | public String nameof() { 35 | return ops.get(op); 36 | } 37 | 38 | public String addrof() { 39 | switch (opreg) { 40 | case Op.R_NONE: return ""; 41 | case Op.R_ABS: return "@"+ java.lang.Long.toHexString(opnd); 42 | case Op.R_IMM: return String.valueOf(opnd); 43 | case Op.R_STACK: return "stack:" + String.valueOf(opnd); 44 | case Op.R_HEAP: return "heap:" + String.valueOf(opnd); 45 | } 46 | return String.valueOf(opreg)+":"+String.valueOf(opnd); 47 | } 48 | 49 | public void printb(PrintStream f) { 50 | long x = opnd; 51 | f.print((char)op); 52 | f.print((char)opreg); 53 | for(int i = 0; i < 6; i++) { 54 | f.print((char)(x & 0xff)); 55 | x = x>>8; 56 | } 57 | } 58 | public void printb() { printb(System.out); } 59 | 60 | public void addr(address a) { 61 | if (a == null) opreg = Op.R_NONE; 62 | else switch (a.region) { 63 | case "method": opreg = Op.R_STACK; opnd = a.offset; break; 64 | case "global": opreg = Op.R_ABS; opnd = a.offset; break; 65 | case "const": opreg = Op.R_ABS; opnd = a.offset; break; 66 | case "lab": opreg = Op.R_ABS; opnd = a.offset; break; 67 | case "obj": opreg = Op.R_HEAP; opnd = a.offset; break; 68 | case "imm": opreg = Op.R_IMM; opnd = a.offset; break; 69 | case "strings": opreg = Op.R_IMM; opnd = a.offset + 24; break; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ch12/classtype.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class classtype extends typeinfo { 3 | String name; 4 | symtab st; 5 | parameter [] methods; 6 | parameter [] fields; 7 | typeinfo [] constrs; 8 | public String str() { 9 | return name; 10 | } 11 | public classtype(String s) { name = s; basetype="class";} 12 | public classtype(String s, symtab stab) { name = s; st = stab; basetype="class";} 13 | public classtype(String s, symtab stab, 14 | parameter []ms, parameter[]fs, typeinfo[]cs) { 15 | name = s; st = stab; methods=ms; fields=fs; constrs=cs; basetype="class";} 16 | } 17 | -------------------------------------------------------------------------------- /ch12/hello.icn: -------------------------------------------------------------------------------- 1 | link printf 2 | procedure main() 3 | s := sprintf("0x%x", 5252) 4 | write("s is ", s) 5 | end 6 | -------------------------------------------------------------------------------- /ch12/hello.j0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Build-Your-Own-Programming-Language/714a2367238d52144843a871b68f908fdee5f5b2/ch12/hello.j0 -------------------------------------------------------------------------------- /ch12/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch12/j0x.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | if not (filename := argv[1]) then 3 | stop("usage: j0x file[.j0]") 4 | if not (filename[-3:0] == ".j0") then filename ||:= ".j0" 5 | j0machine := j0machine() 6 | j0machine.init(filename) 7 | j0machine.interp() 8 | end 9 | -------------------------------------------------------------------------------- /ch12/j0x.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class j0x { 3 | public static void main(String[] argv) { 4 | if (argv.length < 1) { 5 | System.err.println("usage: j0x file[.j0]" + argv.length); 6 | System.exit(1); 7 | } 8 | String filename = argv[0]; 9 | if (! filename.endsWith(".j0")) 10 | filename = filename + ".j0"; 11 | try { 12 | j0machine.init(filename); 13 | } catch(Exception ex) { 14 | System.err.println("Can't initialize. Exiting."); 15 | System.exit(1); 16 | } 17 | j0machine.interp(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch12/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u typeinfo.u 6 | CGU=tac.u address.u byc.u op.u 7 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) $(CGU) 8 | UX=j0x.u j0machine.u op.u 9 | 10 | unicon: j0 j0x 11 | %.u : %.icn 12 | unicon -c $< 13 | j0: $(U) 14 | unicon $(U) 15 | javalex.icn: javalex.l 16 | uflex javalex.l 17 | j0gram.icn j0gram_tab.icn: j0gram.y 18 | iyacc -dd j0gram.y 19 | j0x: $(UX) 20 | unicon $(UX) 21 | 22 | 23 | # A typical run might use 24 | # set CLASSPATH=".;c:\users\username\byopl" 25 | # in order to run from c:\users\username\byopl\ch12 26 | LYSRC=Yylex.java parser.java parserVal.java 27 | TPJ=typeinfo.java arraytype.java classtype.java methodtype.java parameter.java 28 | STJ=symtab.java symtab_entry.java $(TPJ) 29 | CGJ=tac.java address.java byc.java op.java 30 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) $(CGJ) 31 | JXSRC= Op.java j0x.java j0machine.java 32 | BYJOPTS= -Jclass=parser -Jpackage=ch12 33 | BYJIMPS= -Jyylex=ch12.j0.yylex -Jyyerror=ch12.yyerror.yyerror 34 | java: j0.class j0x.class 35 | 36 | j: java 37 | java ch12.j0 hello.java 38 | dot -Tpng hello.java.dot >hello.png 39 | 40 | j0.class: $(JSRC) 41 | javac $(JSRC) 42 | parser.java parserVal.java: j0gram.y 43 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 44 | Yylex.java: javalex.l 45 | jflex javalex.l 46 | 47 | j0x.class: $(JXSRC) 48 | javac $(JXSRC) 49 | -------------------------------------------------------------------------------- /ch12/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class methodtype extends typeinfo { 3 | typeinfo [] parameters; 4 | typeinfo return_type; 5 | public String str() { 6 | String s; 7 | s = "method " + ((return_type!=null)?return_type.str():"undef") + "("; 8 | for(typeinfo p : parameters) 9 | s = s + p.str() + ","; 10 | s = s.substring(0,s.length()-2) + ")"; 11 | return s; 12 | } 13 | methodtype(typeinfo [] p, typeinfo rt){ 14 | parameters = p; 15 | if (rt !=null) return_type = rt; 16 | else return_type = new typeinfo("void"); 17 | basetype="method"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch12/parameter.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch12/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch12/serial.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch12/symtab.icn: -------------------------------------------------------------------------------- 1 | # t is the actual hash table, L holds keys in the order inserted 2 | class symtab(scope, parent, t, L, count) 3 | method lookup(s) 4 | return if rv := \ (t[s]) then { 5 | rv } 6 | else { 7 | (\parent).lookup(s) 8 | } 9 | end 10 | method insert(s, isConst, sub, typ) 11 | if \ (t[s]) then { 12 | if scope == "strings" then { 13 | # write("eureka, a duplicate string constant") 14 | } 15 | else 16 | j0.semErr("redeclaration of " || s) 17 | } 18 | else { 19 | (\sub).parent := self 20 | t[s] := symtab_entry(s, self, sub, isConst, typ, 21 | address(scope,count)) 22 | put(L, s) 23 | len := *s 24 | while len > 0 do { 25 | count +:= 8 26 | len -:= 8 27 | } 28 | } 29 | end 30 | method genlocal() 31 | local s := "__local$" || count 32 | insert(s, false, , typeinfo("int")) 33 | return t[s].addr 34 | end 35 | method print(level:0) 36 | writes(repl(" ",level)) 37 | write(scope, " - ", *t, " symbols") 38 | every (!t).print(level+1); 39 | end 40 | 41 | initially 42 | t := table() 43 | L := [ ] 44 | count := 0 45 | end 46 | -------------------------------------------------------------------------------- /ch12/symtab.java: -------------------------------------------------------------------------------- 1 | package ch12; 2 | import java.util.HashMap; 3 | import java.util.ArrayList; 4 | public class symtab { 5 | String scope; 6 | symtab parent; 7 | HashMap t; 8 | ArrayList L; 9 | int count; 10 | symtab(String sc) { 11 | scope = sc; 12 | t = new HashMap(); 13 | L = new ArrayList(); 14 | } 15 | symtab(String sc, symtab p) { 16 | scope = sc; parent = p; 17 | t = new HashMap(); 18 | L = new ArrayList(); 19 | } 20 | symtab_entry lookup(String s) { 21 | symtab_entry rv; 22 | rv = t.get(s); 23 | if (rv != null) { 24 | return rv; 25 | } 26 | if (parent != null) return parent.lookup(s); 27 | return null; 28 | } 29 | void insert(String s, Boolean iC, symtab sub, typeinfo typ) { 30 | if (t.containsKey(s)) { 31 | j0.semErr("redeclaration of " + s); 32 | } else { 33 | if (sub != null) 34 | sub.parent = this; 35 | t.put(s, new symtab_entry(s, this, iC, sub, typ, 36 | new address(scope,count))); 37 | L.add(s); 38 | int len = s.length(); 39 | while(len > 0) { 40 | count += 8; 41 | len -= 8; 42 | } 43 | } 44 | } 45 | address genlocal() { 46 | String s = "__local$" + count; 47 | insert(s, false, null, new typeinfo("int")); 48 | return t.get(s).addr; 49 | } 50 | void insert(String s, Boolean iC) { 51 | if (t.containsKey(s)) { 52 | j0.semErr("redeclaration of " + s); 53 | } else { 54 | t.put(s, new symtab_entry(s, this, iC)); 55 | } 56 | } 57 | void print() { print(0); } 58 | void print(int level) { 59 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch13/Op.icn: -------------------------------------------------------------------------------- 1 | class Op(HALT, NOOP, ADD, SUB, MUL, DIV, MOD, NEG, PUSH, POP, CALL, RETURN, 2 | GOTO, BIF, LT, LE, GT, GE, EQ, NEQ, LOCAL, LOAD, STORE, 3 | LABEL, STRING, CODE, PROC, GLOBAL, END, 4 | R_NONE, R_ABS, R_IMM, R_STACK, R_HEAP) 5 | initially 6 | HALT := 1; NOOP := 2; ADD := 3; SUB := 4; MUL := 5 7 | DIV := 6; MOD := 7; NEG := 8; PUSH := 9; POP := 10 8 | CALL := 11; RETURN := 12; GOTO := 13; BIF := 14; LT := 15 9 | LE := 16; GT := 17; GE := 18; EQ := 19; NEQ := 20; 10 | LOCAL := 21; LOAD := 22; STORE := 23; 11 | LABEL := 101; STRING:=102; CODE:=103; PROC:=104; GLOBAL := 105; END := 106 12 | R_NONE := 0; R_ABS := 1; R_IMM := 2 13 | R_STACK := 3; R_HEAP := 4 14 | Op := self 15 | end 16 | 17 | procedure OpStr(i) 18 | if type(Op)~=="Op__state" then Op() 19 | case i of { 20 | Op.HALT: return "HALT" 21 | Op.NOOP: return "NOOP" 22 | Op.ADD: return "ADD" 23 | Op.SUB: return "SUB" 24 | Op.MUL: return "MUL" 25 | Op.DIV: return "DIV" 26 | Op.MOD: return "MOD" 27 | Op.NEG: return "NEG" 28 | Op.PUSH: return "PUSH" 29 | Op.POP: return "POP" 30 | Op.CALL: return "CALL" 31 | Op.RETURN: return "RETURN" 32 | Op.GOTO: return "GOTO" 33 | Op.BIF: return "BIF" 34 | Op.LT: return "LT" 35 | Op.LE: return "LE" 36 | Op.GT: return "GT" 37 | Op.GE: return "GE" 38 | Op.EQ: return "EQ" 39 | Op.NEQ: return "NEQ" 40 | Op.LOCAL: return "LOCAL" 41 | Op.LOAD: return "LOAD" 42 | Op.STORE: return "STORE" 43 | default: return "(unknown:"||image(i)||")" 44 | } 45 | end 46 | 47 | procedure OpRStr(opr) 48 | if type(Op)~=="Op__state" then Op() 49 | case opr of { 50 | Op.R_NONE: return "NONE" 51 | Op.R_ABS: return "ABS" 52 | Op.R_IMM: return "IMM" 53 | Op.R_STACK: return "STACK" 54 | Op.R_HEAP: return "HEAP" 55 | } 56 | end 57 | -------------------------------------------------------------------------------- /ch13/Op.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class Op { 3 | public final static short HALT=1, NOOP=2, ADD=3, SUB=4, 4 | MUL=5, DIV=6, MOD=7, NEG=8, PUSH=9, POP=10, CALL=11, 5 | RETURN=12, GOTO=13, BIF=14, LT=15, LE=16, GT=17, GE=18, 6 | EQ=19, NEQ=20, LOCAL=21, LOAD=22, STORE=23; 7 | public final static short LABEL=101, STRING=102, 8 | CODE=103, PROC=104, GLOBAL=105, END=106; 9 | public final static short R_NONE=0, R_ABS=1, R_IMM=2, R_STACK=3, R_HEAP=4; 10 | } 11 | -------------------------------------------------------------------------------- /ch13/RegUse.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | import java.util.ArrayList; 3 | public class RegUse { 4 | public String reg; 5 | int offset; 6 | public boolean loaded, dirty; 7 | public RegUse(String s, int i) { reg = s; offset=i; loaded=dirty=false; } 8 | public ArrayList load() { 9 | if (loaded) return null; 10 | loaded = true; 11 | return j0.xgen("movq", offset+"(%rbp)", reg); 12 | } 13 | public ArrayList save() { 14 | if (!dirty) return null; 15 | dirty = false; 16 | return j0.xgen("movq", reg, offset+"(%rbp)"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch13/address.icn: -------------------------------------------------------------------------------- 1 | class address(region, offset) 2 | method regaddr() 3 | return if region == "method" then "loc" else region 4 | end 5 | method str() 6 | if region=="lab" then return "L"||offset 7 | return regaddr() || ":" || offset 8 | end 9 | method intgr() 10 | if region=="imm" then return integer(offset) 11 | end 12 | method print() 13 | writes(str()) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /ch13/address.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class address { 3 | public String region; 4 | public int offset; 5 | public String regaddr() { return region.equals("method")?"loc":region; } 6 | public String str() { 7 | if (region.equals("lab")) return "L"+offset; 8 | return regaddr() + ":" + offset; } 9 | public int intgr() { 10 | if (region.equals("imm")) return offset; 11 | System.err.println("intgr() on region " + region); 12 | return 0; 13 | } 14 | public void print() { System.out.print(str()); } 15 | address(String s, int o) { region = s; offset = o; } 16 | } 17 | -------------------------------------------------------------------------------- /ch13/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class arraytype extends typeinfo { 3 | typeinfo element_type; 4 | public String str() { 5 | return "array of " + (element_type!=null?element_type.str():"undef"); 6 | } 7 | public arraytype(typeinfo t) { 8 | basetype = "array"; element_type = t; } 9 | } 10 | -------------------------------------------------------------------------------- /ch13/byc.icn: -------------------------------------------------------------------------------- 1 | link printf 2 | class byc(op, opreg, opnd) 3 | method print(f:&output) 4 | write(f, "\t", nameof(), " ", addrof()) | 5 | write(&errout, "can't print ", image(self), " op ", image(op)) 6 | end 7 | method nameof() 8 | static opnames 9 | initial opnames := table(Op.HALT, "halt", Op.NOOP, "noop", 10 | Op.ADD, "add", Op.SUB, "sub", Op.MUL, "mul", 11 | Op.DIV, "div", Op.MOD, "mod", Op.NEG, "neg", 12 | Op.PUSH, "push", Op.POP, "pop", Op.CALL, "call", 13 | Op.RETURN, "return", Op.GOTO, "goto", Op.BIF, "bif", 14 | Op.LT, "lt", Op.LE, "le", Op.GT, "gt", Op.GE, "ge", 15 | Op.EQ, "eq", Op.NEQ, "neq", Op.LOCAL, "local", 16 | Op.LOAD, "load", Op.STORE, "store", Op.LABEL, "LABEL", 17 | Op.STRING, "STRING", Op.CODE, "CODE", Op.PROC, "PROC", 18 | Op.GLOBAL, "GLOBAL", Op.END, "END") 19 | return opnames[op] 20 | end 21 | method addrof() 22 | case opreg of { 23 | Op.R_NONE | &null: return "" 24 | Op.R_ABS: return "@" || sprintf("%x",opnd) 25 | Op.R_IMM: return string(opnd) 26 | Op.R_STACK: return "stack:" || opnd 27 | Op.R_HEAP: return "heap:" || opnd 28 | default: { 29 | return string(opreg) || ":" || opnd 30 | } 31 | } 32 | end 33 | 34 | method printb(f:&output) 35 | writes(f, char(op), char(\opreg|0)) 36 | x := (\opnd | 0) 37 | every !6 do { 38 | writes(f, char(iand(x, 255))) 39 | x := ishift(x, -8) 40 | } 41 | end 42 | method addr(a) 43 | if /a then opreg := Op.R_NONE 44 | else if type(a) == "integer" then { 45 | opreg := Op.R_IMM; opnd := a 46 | } 47 | else if type(a) == "string" then { 48 | if not (sa := stringtab.lookup(a)) then write("don't know ", image(a)) 49 | # string region addresses are just pointers offset 24 from start 50 | opreg := Op.R_IMM; opnd := sa.addr.offset + 24 51 | } 52 | else case a.region of { 53 | "method": { opreg := Op.R_STACK; opnd := a.offset } 54 | "global": { opreg := Op.R_ABS; opnd := a.offset + stringtab.count } 55 | "const": { opreg := Op.R_ABS; opnd := a.offset } 56 | "lab": { opreg := Op.R_ABS; opnd := a.offset } 57 | "obj": { opreg := Op.R_HEAP; opnd := a.offset } 58 | "imm": { opreg := Op.R_IMM; opnd := a.offset } 59 | "strings": { opreg := Op.R_IMM; opnd := a.offset + 24 } 60 | default: { 61 | write("system error. region ", image(a.region), 62 | " offset ", image(a.offset)) 63 | runerr(103, a.region) 64 | } 65 | } 66 | end 67 | initially(o, a) 68 | op := o; addr(a); # addr(\a);? 69 | if type(nameof()) ~== "string" then { 70 | write(&errout, "bad op ", image(op)) 71 | runerr(103, op) 72 | } 73 | end 74 | -------------------------------------------------------------------------------- /ch13/byc.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | import java.util.HashMap; 3 | import java.io.PrintStream; 4 | public class byc { 5 | int op, opreg; 6 | long opnd; 7 | public byc(int o, address a) { 8 | op=o; addr(a); 9 | } 10 | public void print(PrintStream f) { 11 | f.println("\t" + nameof() + " " + addrof()); 12 | } 13 | public void print() { 14 | print(System.out); 15 | } 16 | static HashMap ops; 17 | static { ops = new HashMap<>(); 18 | ops.put(Op.HALT,"halt"); ops.put(Op.NOOP,"noop"); 19 | ops.put(Op.ADD,"add"); ops.put(Op.SUB,"sub"); 20 | ops.put(Op.MUL,"mul"); ops.put(Op.DIV, "div"); 21 | ops.put(Op.MOD,"mod"); ops.put(Op.NEG, "neg"); 22 | ops.put(Op.PUSH,"push"); ops.put(Op.POP, "pop"); 23 | ops.put(Op.CALL, "call"); ops.put(Op.RETURN, "return"); 24 | ops.put(Op.GOTO, "goto"); ops.put(Op.BIF, "bif"); 25 | ops.put(Op.LT, "lt"); ops.put(Op.LE, "le"); 26 | ops.put(Op.GT, "gt"); ops.put(Op.GE, "ge"); 27 | ops.put(Op.EQ, "eq"); ops.put(Op.NEQ, "neq"); 28 | ops.put(Op.LOCAL, "local"); ops.put(Op.LOAD, "load"); 29 | ops.put(Op.STORE, "store"); ops.put(Op.LABEL, "LABEL"); 30 | ops.put(Op.STRING, "STRING"); ops.put(Op.CODE, "CODE"); 31 | ops.put(Op.PROC, "PROC"); ops.put(Op.GLOBAL, "GLOBAL"); 32 | ops.put(Op.END, "END"); 33 | } 34 | public String nameof() { 35 | return ops.get(op); 36 | } 37 | 38 | public String addrof() { 39 | switch (opreg) { 40 | case Op.R_NONE: return ""; 41 | case Op.R_ABS: return "@"+ java.lang.Long.toHexString(opnd); 42 | case Op.R_IMM: return String.valueOf(opnd); 43 | case Op.R_STACK: return "stack:" + String.valueOf(opnd); 44 | case Op.R_HEAP: return "heap:" + String.valueOf(opnd); 45 | } 46 | return String.valueOf(opreg)+":"+String.valueOf(opnd); 47 | } 48 | 49 | public void printb(PrintStream f) { 50 | long x = opnd; 51 | f.print((char)op); 52 | f.print((char)opreg); 53 | for(int i = 0; i < 6; i++) { 54 | f.print((char)(x & 0xff)); 55 | x = x>>8; 56 | } 57 | } 58 | public void printb() { printb(System.out); } 59 | 60 | public void addr(address a) { 61 | if (a == null) opreg = Op.R_NONE; 62 | else switch (a.region) { 63 | case "method": opreg = Op.R_STACK; opnd = a.offset; break; 64 | case "global": opreg = Op.R_ABS; opnd = a.offset; break; 65 | case "const": opreg = Op.R_ABS; opnd = a.offset; break; 66 | case "lab": opreg = Op.R_ABS; opnd = a.offset; break; 67 | case "obj": opreg = Op.R_HEAP; opnd = a.offset; break; 68 | case "imm": opreg = Op.R_IMM; opnd = a.offset; break; 69 | case "strings": opreg = Op.R_IMM; opnd = a.offset + 24; break; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ch13/classtype.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class classtype extends typeinfo { 3 | String name; 4 | symtab st; 5 | parameter [] methods; 6 | parameter [] fields; 7 | typeinfo [] constrs; 8 | public String str() { 9 | return name; 10 | } 11 | public classtype(String s) { name = s; basetype="class";} 12 | public classtype(String s, symtab stab) { name = s; st = stab; basetype="class";} 13 | public classtype(String s, symtab stab, 14 | parameter []ms, parameter[]fs, typeinfo[]cs) { 15 | name = s; st = stab; methods=ms; fields=fs; constrs=cs; basetype="class";} 16 | } 17 | -------------------------------------------------------------------------------- /ch13/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch13/j0x.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | if not (filename := argv[1]) then 3 | stop("usage: j0x file[.j0]") 4 | if not (filename[-3:0] == ".j0") then filename ||:= ".j0" 5 | j0machine := j0machine() 6 | j0machine.init(filename) 7 | j0machine.interp() 8 | end 9 | -------------------------------------------------------------------------------- /ch13/j0x.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class j0x { 3 | public static void main(String[] argv) { 4 | if (argv.length < 1) { 5 | System.err.println("usage: j0x file[.j0]" + argv.length); 6 | System.exit(1); 7 | } 8 | String filename = argv[0]; 9 | if (! filename.endsWith(".j0")) 10 | filename = filename + ".j0"; 11 | try { 12 | j0machine.init(filename); 13 | } catch(Exception ex) { 14 | System.err.println("Can't initialize. Exiting."); 15 | System.exit(1); 16 | } 17 | j0machine.interp(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch13/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u typeinfo.u 6 | CGU=tac.u address.u byc.u op.u reguse.u x64.u x64loc.u 7 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) $(CGU) 8 | UX=j0x.u j0machine.u op.u 9 | 10 | unicon: j0 j0x 11 | %.u : %.icn 12 | unicon -c $< 13 | j0: $(U) 14 | unicon $(U) 15 | javalex.icn: javalex.l 16 | uflex javalex.l 17 | j0gram.icn j0gram_tab.icn: j0gram.y 18 | iyacc -dd j0gram.y 19 | j0x: $(UX) 20 | unicon $(UX) 21 | 22 | # A typical run might use 23 | # set CLASSPATH=".;c:\users\username\byopl" 24 | # in order to run from c:\users\username\byopl\ch13 25 | LYSRC=Yylex.java parser.java parserVal.java 26 | TPJ=typeinfo.java arraytype.java classtype.java methodtype.java parameter.java 27 | STJ=symtab.java symtab_entry.java $(TPJ) 28 | CGJ=tac.java address.java byc.java op.java RegUse.java x64.java x64loc.java 29 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) $(CGJ) 30 | JXSRC= Op.java j0x.java j0machine.java 31 | BYJOPTS= -Jclass=parser -Jpackage=ch13 32 | BYJIMPS= -Jyylex=ch13.j0.yylex -Jyyerror=ch13.yyerror.yyerror 33 | java: j0.class j0x.class 34 | 35 | j: java 36 | java ch13.j0 hello.java 37 | dot -Tpng hello.java.dot >hello.png 38 | 39 | j0.class: $(JSRC) 40 | CLASSPATH=".;D:\Users\Clinton Jeffery\books\byopl" javac $(JSRC) 41 | parser.java parserVal.java: j0gram.y 42 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 43 | Yylex.java: javalex.l 44 | jflex javalex.l 45 | 46 | j0x.class: $(JXSRC) 47 | javac $(JXSRC) 48 | -------------------------------------------------------------------------------- /ch13/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class methodtype extends typeinfo { 3 | typeinfo [] parameters; 4 | typeinfo return_type; 5 | public String str() { 6 | String s; 7 | s = "method " + ((return_type!=null)?return_type.str():"undef") + "("; 8 | for(typeinfo p : parameters) 9 | s = s + p.str() + ","; 10 | s = s.substring(0,s.length()-2) + ")"; 11 | return s; 12 | } 13 | methodtype(typeinfo [] p, typeinfo rt){ 14 | parameters = p; 15 | if (rt !=null) return_type = rt; 16 | else return_type = new typeinfo("void"); 17 | basetype="method"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch13/parameter.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch13/reguse.icn: -------------------------------------------------------------------------------- 1 | class RegUse (reg, offset, loaded, dirty) 2 | method load() 3 | if \loaded then fail 4 | loaded := 1 5 | return j0.xgen("movq", offset||"(%rbp)", reg) 6 | end 7 | method save() 8 | if /dirty then fail 9 | dirty := &null 10 | return j0.xgen("movq", reg, offset||"(%rbp)") 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /ch13/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch13/serial.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch13/symtab.icn: -------------------------------------------------------------------------------- 1 | # t is the actual hash table, L holds keys in the order inserted 2 | class symtab(scope, parent, t, L, count) 3 | method lookup(s) 4 | return if rv := \ (t[s]) then { 5 | rv } 6 | else { 7 | (\parent).lookup(s) 8 | } 9 | end 10 | method insert(s, isConst, sub, typ) 11 | if \ (t[s]) then { 12 | if scope == "strings" then { 13 | # write("eureka, a duplicate string constant") 14 | } 15 | else 16 | j0.semErr("redeclaration of " || s) 17 | } 18 | else { 19 | (\sub).parent := self 20 | t[s] := symtab_entry(s, self, sub, isConst, typ, 21 | address(scope,count)) 22 | put(L, s) 23 | len := *s 24 | while len > 0 do { 25 | count +:= 8 26 | len -:= 8 27 | } 28 | } 29 | end 30 | method genlocal() 31 | local s := "__local$" || count 32 | insert(s, false, , typeinfo("int")) 33 | return t[s].addr 34 | end 35 | method print(level:0) 36 | writes(repl(" ",level)) 37 | write(scope, " - ", *t, " symbols") 38 | every (!t).print(level+1); 39 | end 40 | 41 | initially 42 | t := table() 43 | L := [ ] 44 | count := 0 45 | end 46 | -------------------------------------------------------------------------------- /ch13/symtab.java: -------------------------------------------------------------------------------- 1 | package ch13; 2 | import java.util.HashMap; 3 | import java.util.ArrayList; 4 | public class symtab { 5 | String scope; 6 | symtab parent; 7 | HashMap t; 8 | ArrayList L; 9 | int count; 10 | symtab(String sc) { 11 | scope = sc; 12 | t = new HashMap(); 13 | L = new ArrayList(); 14 | } 15 | symtab(String sc, symtab p) { 16 | scope = sc; parent = p; 17 | t = new HashMap(); 18 | L = new ArrayList(); 19 | } 20 | symtab_entry lookup(String s) { 21 | symtab_entry rv; 22 | rv = t.get(s); 23 | if (rv != null) { 24 | return rv; 25 | } 26 | if (parent != null) return parent.lookup(s); 27 | return null; 28 | } 29 | void insert(String s, Boolean iC, symtab sub, typeinfo typ) { 30 | if (t.containsKey(s)) { 31 | j0.semErr("redeclaration of " + s); 32 | } else { 33 | if (sub != null) 34 | sub.parent = this; 35 | t.put(s, new symtab_entry(s, this, iC, sub, typ, 36 | new address(scope,count))); 37 | L.add(s); 38 | int len = s.length(); 39 | while(len > 0) { 40 | count += 8; 41 | len -= 8; 42 | } 43 | } 44 | } 45 | address genlocal() { 46 | String s = "__local$" + count; 47 | insert(s, false, null, new typeinfo("int")); 48 | return t.get(s).addr; 49 | } 50 | void insert(String s, Boolean iC) { 51 | if (t.containsKey(s)) { 52 | j0.semErr("redeclaration of " + s); 53 | } else { 54 | t.put(s, new symtab_entry(s, this, iC)); 55 | } 56 | } 57 | void print() { print(0); } 58 | void print(int level) { 59 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch3/dorrie.in: -------------------------------------------------------------------------------- 1 | Dr J is 1 fine puppy -------------------------------------------------------------------------------- /ch3/dorrie2.in: -------------------------------------------------------------------------------- 1 | Dorrie 2 | is 1 3 | fine puppy. 4 | -------------------------------------------------------------------------------- /ch3/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch3/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yylineno, yylval 2 | procedure main(argv) 3 | j0 := j0() 4 | parser := parser(257,258,259,260,261,262,263,264,265,266, 5 | 267,268,269,270,273,274,275, 6 | 276,277,278,280, 7 | 298,300,301, 8 | 302,303,304,306, 9 | 307,256) 10 | yyin := open(argv[1]) | stop("usage: simple2 filename") 11 | yylineno := 1 12 | while i := yylex() do 13 | write(yytext, ":",yylval.lineno, " ", i) 14 | end 15 | class j0() 16 | method lexErr(s) 17 | stop(s, ": ", yytext) 18 | end 19 | method scan(cat) 20 | yylval := token(cat, yytext, yylineno) 21 | return cat 22 | end 23 | method whitespace() 24 | end 25 | method newline() 26 | yylineno +:= 1 27 | end 28 | method comment() 29 | end 30 | method ord(s) 31 | return proc("ord",0)(s[1]) 32 | end 33 | end 34 | record token(cat, text, lineno) 35 | record parser(BREAK,PUBLIC,DOUBLE,ELSE,FOR,IF,INT,RETURN,VOID,WHILE, 36 | IDENTIFIER,CLASSNAME,CLASS,STATIC,STRING,BOOL,INTLIT, 37 | DOUBLELIT,STRINGLIT,BOOLLIT,NULLVAL, 38 | LESSTHANOREQUAL,GREATERTHANOREQUAL,ISEQUALTO, 39 | NOTEQUALTO,LOGICALAND,LOGICALOR,INCREMENT, 40 | DECREMENT,YYERRCODE) 41 | -------------------------------------------------------------------------------- /ch3/j0.java: -------------------------------------------------------------------------------- 1 | import java.io.FileReader; 2 | public class j0 { 3 | static Yylex lex; 4 | public static int yylineno; 5 | public static token yylval; 6 | public static void main(String argv[]) throws Exception { 7 | lex = new Yylex(new FileReader(argv[0])); 8 | yylineno = 1; 9 | int i; 10 | while ((i=lex.yylex()) != Yylex.YYEOF) { 11 | System.out.println("token " + i + ": " + yytext()); 12 | } 13 | } 14 | public static String yytext() { 15 | return lex.yytext(); 16 | } 17 | public static void lexErr(String s) { 18 | System.err.println(s + ": line " + yylineno + 19 | ": " + yytext()); 20 | System.exit(1); 21 | } 22 | public static int scan(int cat) { 23 | yylval = new token(cat, yytext(), yylineno); 24 | return cat; 25 | } 26 | public static void newline() { 27 | yylineno++; 28 | } 29 | public static void whitespace() { 30 | } 31 | public static void comment() { 32 | } 33 | public static short ord(String s) { return (short)(s.charAt(0)); } 34 | } 35 | -------------------------------------------------------------------------------- /ch3/j0go.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yylineno, last_token 2 | procedure main(argv) 3 | j0 := j0() 4 | parser := parser(257,259,260,261,262,263,264,265,266,267, 5 | 268,269,273,274,275,276,277,278,280,298, 6 | 300,301,302,303,304,306,307,256) 7 | yyin := open(argv[1]) | stop("usage: simple2 filename") 8 | yylineno := 1 9 | while i := yylex() do 10 | write(yytext, ":",yylval.lineno, " ", i) 11 | end 12 | class j0() 13 | method lexErr(s) 14 | stop(s, ": ", yytext) 15 | end 16 | method scan(cat) 17 | last_token := yylval := token(cat, yytext, yylineno) 18 | return cat 19 | end 20 | method newline() 21 | yylineno +:= 1 22 | if (\last_token).cat === 23 | ( parser.IDENTIFIER|parser.INTLIT|parser.DOUBLELIT| 24 | parser.STRINGLIT|parser.BREAK|parser.RETURN| 25 | parser.INCREMENT|parser.DECREMENT| 26 | ord(!")]}") ) then return 27 | end 28 | method semicolon() 29 | yytext := ";" 30 | yylineno -:= 1 31 | return scan(parser.SEMICOLON) 32 | end 33 | method ord(s) 34 | return proc("ord",0)(s[1]) 35 | end 36 | method whitespace() 37 | end 38 | method comment() 39 | end 40 | end 41 | record token(cat, text, lineno) 42 | record parser(BREAK,DOUBLE,ELSE,FOR,IF,INT,RETURN,VOID,WHILE, 43 | IDENTIFIER,CLASSNAME,CLASS,STRING,BOOL,INTLIT, 44 | DOUBLELIT,STRINGLIT,BOOLLIT,NULLVAL, 45 | LESSTHANOREQUAL,GREATERTHANOREQUAL,ISEQUALTO, 46 | NOTEQUALTO,LOGICALAND,LOGICALOR,INCREMENT, 47 | DECREMENT,YYERRCODE) 48 | -------------------------------------------------------------------------------- /ch3/j0go.java: -------------------------------------------------------------------------------- 1 | import java.io.FileReader; 2 | public class j0go { 3 | static Yylex lex; 4 | public static int yylineno, yycolno; 5 | public static token yylval; 6 | public static void main(String argv[]) throws Exception { 7 | lex = new Yylex(new FileReader(argv[0])); 8 | yylineno = yycolno = 1; 9 | int i; 10 | while ((i=lex.yylex()) != Yylex.YYEOF) { 11 | System.out.println("token " + i + ": " + yytext()); 12 | } 13 | } 14 | public static String yytext() { 15 | return lex.yytext(); 16 | } 17 | public static void lexErr(String s) { 18 | System.err.println(s + ": line " + yylineno + 19 | ": " + yytext()); 20 | System.exit(1); 21 | } 22 | public static int scan(int cat) { 23 | last_token = yylval = 24 | new token(cat, yytext(), yylineno); 25 | yycolno += yytext().length(); 26 | return cat; 27 | } 28 | public static void newline() { 29 | yylineno++; yycolno = 1; 30 | if (last_token != null) 31 | switch(last_token.cat) { 32 | case parser.IDENTIFIER: case parser.INTLIT: 33 | case parser.DOUBLELIT: case parser.STRINGLIT: 34 | case parser.BREAK: case parser.RETURN: 35 | case parser.INCREMENT: case parser.DECREMENT: 36 | case ')': case ']': case '}': 37 | return true; 38 | } 39 | return false; 40 | } 41 | public static int semicolon() { 42 | yytext = ";"; 43 | yylineno--; 44 | return scan(parser.SEMICOLON); 45 | } 46 | public static void whitespace() { 47 | yycolno += yytext().length(); 48 | } 49 | public static void comment() { 50 | int i, len; 51 | String s = yytext(); 52 | len = s.length(); 53 | for(i=0; i" { return j0.scan(j0.ord(">"));} 43 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 44 | "==" { return j0.scan(parser.ISEQUALTO);} 45 | "!=" { return j0.scan(parser.NOTEQUALTO);} 46 | "&&" { return j0.scan(parser.LOGICALAND);} 47 | "||" { return j0.scan(parser.LOGICALOR);} 48 | "=" { return j0.scan(j0.ord("=")); } 49 | "+=" { return j0.scan(parser.INCREMENT); } 50 | "-=" { return j0.scan(parser.DECREMENT); } 51 | "," { return j0.scan(j0.ord(",")); } 52 | "." { return j0.scan(j0.ord(".")); } 53 | {id} { return j0.scan(parser.IDENTIFIER); } 54 | [0-9]+ { return j0.scan(parser.INTLIT); } 55 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 56 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 57 | \"[^\"]*\" { return j0.scan(parser.STRINGLIT); } 58 | . { j0.lexErr("unrecognized character"); } 59 | -------------------------------------------------------------------------------- /ch3/nnws-tok.l: -------------------------------------------------------------------------------- 1 | %% 2 | %int 3 | %% 4 | [a-zA-Z]+ { return simple2.scan(1); } 5 | [0-9]+ { return simple2.scan(2); } 6 | [ \t]+ { } 7 | \r?\n { simple2.increment_lineno(); } 8 | . { simple2.lexErr("unrecognized character"); } 9 | -------------------------------------------------------------------------------- /ch3/nnws.l: -------------------------------------------------------------------------------- 1 | %% 2 | %int 3 | %% 4 | [a-zA-Z]+ { return 1; } 5 | [0-9]+ { return 2; } 6 | [ \t]+ { } 7 | . { simple.lexErr("unrecognized character"); } 8 | -------------------------------------------------------------------------------- /ch3/parser.java: -------------------------------------------------------------------------------- 1 | // stand-in for an iyacc parser object, gives terminal symbols 2 | public class parser { 3 | public final static short BREAK=257; 4 | public final static short PUBLIC=258; 5 | public final static short DOUBLE=259; 6 | public final static short ELSE=260; 7 | public final static short FOR=261; 8 | public final static short IF=262; 9 | public final static short INT=263; 10 | public final static short RETURN=264; 11 | public final static short VOID=265; 12 | public final static short WHILE=266; 13 | public final static short IDENTIFIER=267; 14 | public final static short CLASSNAME=268; 15 | public final static short CLASS=269; 16 | public final static short STATIC=270; 17 | public final static short STRING=273; 18 | public final static short BOOL=274; 19 | public final static short INTLIT=275; 20 | public final static short DOUBLELIT=276; 21 | public final static short STRINGLIT=277; 22 | public final static short BOOLLIT=278; 23 | public final static short NULLVAL=280; 24 | public final static short LESSTHANOREQUAL=298; 25 | public final static short GREATERTHANOREQUAL=300; 26 | public final static short ISEQUALTO=301; 27 | public final static short NOTEQUALTO=302; 28 | public final static short LOGICALAND=303; 29 | public final static short LOGICALOR=304; 30 | public final static short INCREMENT=306; 31 | public final static short DECREMENT=307; 32 | public final static short YYERRCODE=256; 33 | } 34 | -------------------------------------------------------------------------------- /ch3/simple.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | simple := simple() 3 | yyin := open(argv[1]) 4 | while i := yylex() do 5 | write(yytext, ": ", i) 6 | end 7 | class simple() 8 | method lexErr(s) 9 | stop(s, ": ", yytext) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /ch3/simple.java: -------------------------------------------------------------------------------- 1 | import java.io.FileReader; 2 | public class simple { 3 | static Yylex yylexer; 4 | public static String yytext() { 5 | return yylexer.yytext(); 6 | } 7 | public static void lexErr(String s) { 8 | System.err.println(s + ": " + yytext()); 9 | System.exit(1); 10 | } 11 | public static void main(String argv[]) throws Exception { 12 | if (argv.length == 0) { 13 | System.out.println("usage: java simple [file]"); 14 | } 15 | yylexer = new Yylex(new FileReader(argv[0])); 16 | int i; 17 | while ((i=yylexer.yylex()) != Yylex.YYEOF) { 18 | System.out.println("token " + i + ": " + yytext()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch3/simple2.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yylval 2 | procedure main(argv) 3 | simple2 := simple2() 4 | yyin := open(argv[1]) | stop("usage: simple2 filename") 5 | yylineno := 1 6 | while i := yylex() do 7 | write("token ", i, " (line ", yylval.lineno, "): ", yytext) 8 | end 9 | class simple2() 10 | method lexErr(s) 11 | stop(s, ": line ", yylineno, ": ", yytext) 12 | end 13 | method scan(cat) 14 | yylval := token(cat, yytext, yylineno) 15 | return cat 16 | end 17 | method increment_lineno() 18 | yylineno +:= 1 19 | end 20 | end 21 | record token(cat, text, lineno) 22 | -------------------------------------------------------------------------------- /ch3/simple2.java: -------------------------------------------------------------------------------- 1 | import java.io.FileReader; 2 | public class simple2 { 3 | static Yylex lex; 4 | public static int yylineno; 5 | public static token yylval; 6 | public static void main(String argv[]) throws Exception { 7 | lex = new Yylex(new FileReader(argv[0])); 8 | yylineno = 1; 9 | int i; 10 | while ((i=lex.yylex()) != Yylex.YYEOF) { 11 | System.out.println("token " + i + 12 | " (line " + yylval.lineno + "): " + yytext()); 13 | } 14 | } 15 | public static String yytext() { 16 | return lex.yytext(); 17 | } 18 | public static void lexErr(String s) { 19 | System.err.println(s + ": line " + yylineno + 20 | ": " + yytext()); 21 | System.exit(1); 22 | } 23 | public static int scan(int cat) { 24 | yylval = new token(cat, yytext(), yylineno); 25 | return cat; 26 | } 27 | public static void increment_lineno() { 28 | yylineno++; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ch3/token.java: -------------------------------------------------------------------------------- 1 | public class token { 2 | public int cat; 3 | public String text; 4 | public int lineno; 5 | public token(int c, String s, int l) { 6 | cat = c; text = s; lineno = l; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ch4/dorrie3.in: -------------------------------------------------------------------------------- 1 | Dorrie 1 Clint 0 -------------------------------------------------------------------------------- /ch4/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch4/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch4/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yycolno, yylval, parser 2 | procedure main(argv) 3 | j0 := j0() 4 | parser := Parser() 5 | yyin := open(argv[1]) | stop("usage: j0 filename") 6 | yylineno := yycolno := 1 7 | if yyparse() = 0 then 8 | write("no errors, ", j0.count, " tokens parsed") 9 | end 10 | class j0(count) 11 | method lexErr(s) 12 | stop(s, ": ", yytext) 13 | end 14 | method scan(cat) 15 | yylval := token(cat, yytext, yylineno, yycolno) 16 | yycolno +:= *yytext 17 | count +:= 1 18 | return cat 19 | end 20 | method whitespace() 21 | yycolno +:= *yytext 22 | end 23 | method newline() 24 | yylineno +:= 1; yycolno := 1 25 | end 26 | method comment() 27 | yytext ? { 28 | while tab(find("\n")+1) do newline() 29 | yycolno +:= *tab(0) 30 | } 31 | end 32 | method ord(s) 33 | return proc("ord",0)(s[1]) 34 | end 35 | initially 36 | count := 0 37 | end 38 | class token(cat, text, lineno, colno, ival, dval, sval) 39 | method deEscape(sin) 40 | local sout := "" 41 | sin := sin[2:-1] 42 | sin ? { 43 | while c := move(1) do { 44 | if c == "\\" then { 45 | if not (c := move(1)) then 46 | j0.lexErr("malformed string literal") 47 | else case c of { 48 | "t":{ sout ||:= "\t" } 49 | "n":{ sout ||:= "\n" } 50 | } 51 | } 52 | else sout ||:= c 53 | } 54 | } 55 | return sout 56 | end 57 | initially 58 | case cat of { 59 | parser.INTLIT: { ival := integer(text) } 60 | parser.DOUBLELIT: { dval := real(text) } 61 | parser.STRINGLIT: { sval := deEscape(text) } 62 | } 63 | end 64 | -------------------------------------------------------------------------------- /ch4/j0.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | import java.io.FileReader; 3 | public class j0 { 4 | public static Yylex yylexer; 5 | public static ch4.parser par; 6 | public static int yylineno, yycolno, count; 7 | public static void main(String argv[]) throws Exception { 8 | init(argv[0]); 9 | par = new ch4.parser(); 10 | // par.yydebug=true; 11 | yylineno = yycolno = 1; 12 | count = 0; 13 | int i = par.yyparse(); 14 | if (i == 0) 15 | System.out.println("no errors, " + j0.count + 16 | "tokens parsed"); 17 | } 18 | // public static parserVal yylval; 19 | public static void init(String s) throws Exception { 20 | yylexer = new Yylex(new FileReader(s)); 21 | } 22 | public static int YYEOF() { return Yylex.YYEOF; } 23 | public static int yylex() { 24 | int rv = 0; 25 | try { 26 | rv = yylexer.yylex(); 27 | } catch(java.io.IOException ioException) { 28 | rv = -1; 29 | } 30 | return rv; 31 | } 32 | public static String yytext() { 33 | return yylexer.yytext(); 34 | } 35 | public static void lexErr(String s) { 36 | System.err.println(s); 37 | System.exit(1); 38 | } 39 | public static int scan(int cat) { 40 | ch4.j0.par.yylval = new parserVal( 41 | new token(cat, yytext(), yylineno, yycolno)); 42 | return cat; 43 | } 44 | public static void newline() { 45 | yylineno++; 46 | } 47 | public static void whitespace() { 48 | } 49 | public static void comment() { 50 | } 51 | public static short ord(String s) { return (short)(s.charAt(0)); } 52 | } 53 | -------------------------------------------------------------------------------- /ch4/j0go.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yylineno, last_token 2 | procedure main(argv) 3 | j0 := j0() 4 | parser := parser(257,259,260,261,262,263,264,265,266,267, 5 | 268,269,273,274,275,276,277,278,280,298, 6 | 300,301,302,303,304,306,307,256) 7 | yyin := open(argv[1]) | stop("usage: simple2 filename") 8 | yylineno := 1 9 | while i := yylex() do 10 | write(yytext, ":",yylval.lineno, " ", i) 11 | end 12 | class j0() 13 | method lexErr(s) 14 | stop(s, ": ", yytext) 15 | end 16 | method scan(cat) 17 | last_token := yylval := token(cat, yytext, yylineno) 18 | return cat 19 | end 20 | method newline() 21 | yylineno +:= 1 22 | if (\last_token).cat === 23 | ( parser.IDENTIFIER|parser.INTLIT|parser.DOUBLELIT| 24 | parser.STRINGLIT|parser.BREAK|parser.RETURN| 25 | parser.INCREMENT|parser.DECREMENT| 26 | ord(!")]}") ) then return 27 | end 28 | method semicolon() 29 | yytext := ";" 30 | yylineno -:= 1 31 | return scan(parser.SEMICOLON) 32 | end 33 | method ord(s) 34 | return proc("ord",0)(s[1]) 35 | end 36 | method whitespace() 37 | end 38 | method comment() 39 | end 40 | end 41 | record token(cat, text, lineno) 42 | record parser(BREAK,DOUBLE,ELSE,FOR,IF,INT,RETURN,VOID,WHILE, 43 | IDENTIFIER,CLASSNAME,CLASS,STRING,BOOL,INTLIT, 44 | DOUBLELIT,STRINGLIT,BOOLLIT,NULLVAL, 45 | LESSTHANOREQUAL,GREATERTHANOREQUAL,ISEQUALTO, 46 | NOTEQUALTO,LOGICALAND,LOGICALOR,INCREMENT, 47 | DECREMENT,YYERRCODE) 48 | -------------------------------------------------------------------------------- /ch4/j0go.java: -------------------------------------------------------------------------------- 1 | import java.io.FileReader; 2 | public class j0go { 3 | static Yylex lex; 4 | public static int yylineno, yycolno; 5 | public static token yylval; 6 | public static void main(String argv[]) throws Exception { 7 | lex = new Yylex(new FileReader(argv[0])); 8 | yylineno = yycolno = 1; 9 | int i; 10 | while ((i=lex.yylex()) != Yylex.YYEOF) { 11 | System.out.println("token " + i + ": " + yytext()); 12 | } 13 | } 14 | public static String yytext() { 15 | return lex.yytext(); 16 | } 17 | public static void lexErr(String s) { 18 | System.err.println(s + ": line " + yylineno + 19 | ": " + yytext()); 20 | System.exit(1); 21 | } 22 | public static int scan(int cat) { 23 | last_token = yylval = 24 | new token(cat, yytext(), yylineno); 25 | yycolno += yytext().length(); 26 | return cat; 27 | } 28 | public static void newline() { 29 | yylineno++; yycolno = 1; 30 | if (last_token != null) 31 | switch(last_token.cat) { 32 | case parser.IDENTIFIER: case parser.INTLIT: 33 | case parser.DOUBLELIT: case parser.STRINGLIT: 34 | case parser.BREAK: case parser.RETURN: 35 | case parser.INCREMENT: case parser.DECREMENT: 36 | case ')': case ']': case '}': 37 | return true; 38 | } 39 | return false; 40 | } 41 | public static int semicolon() { 42 | yytext = ";"; 43 | yylineno--; 44 | return scan(parser.SEMICOLON); 45 | } 46 | public static void whitespace() { 47 | yycolno += yytext().length(); 48 | } 49 | public static void comment() { 50 | int i, len; 51 | String s = yytext(); 52 | len = s.length(); 53 | for(i=0; i" { return j0.scan(j0.ord(">"));} 44 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 45 | "==" { return j0.scan(parser.ISEQUALTO);} 46 | "!=" { return j0.scan(parser.NOTEQUALTO);} 47 | "&&" { return j0.scan(parser.LOGICALAND);} 48 | "||" { return j0.scan(parser.LOGICALOR);} 49 | "=" { return j0.scan(j0.ord("=")); } 50 | "+=" { return j0.scan(parser.INCREMENT); } 51 | "-=" { return j0.scan(parser.DECREMENT); } 52 | "," { return j0.scan(j0.ord(",")); } 53 | "." { return j0.scan(j0.ord(".")); } 54 | {id} { return j0.scan(parser.IDENTIFIER); } 55 | [0-9]+ { return j0.scan(parser.INTLIT); } 56 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 57 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 58 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 59 | . { j0.lexErr("unrecognized character"); } 60 | -------------------------------------------------------------------------------- /ch4/jzero.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public class jzero { 3 | public static ch4.parser par; 4 | public static void main(String argv[]) throws Exception { 5 | ch4.j0.init(argv[0]); 6 | par = new ch4.parser(); 7 | yylineno = 1; 8 | int i = par.yyparse(); 9 | if (i == 0) 10 | System.out.println("no errors"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch4/lexer.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | import java.io.FileReader; 3 | public class lexer { 4 | public static Yylex yylexer; 5 | public static void init(String s) throws Exception { 6 | yylexer = new Yylex(new FileReader(s)); 7 | } 8 | public static int YYEOF() { return Yylex.YYEOF; } 9 | public static int yylex() { 10 | int rv = 0; 11 | try { 12 | rv = yylexer.yylex(); 13 | } catch(java.io.IOException ioException) { 14 | rv = -1; 15 | } 16 | return rv; 17 | } 18 | public static String yytext() { 19 | return yylexer.yytext(); 20 | } 21 | public static void lexErr(String s) { 22 | System.err.println(s); 23 | System.exit(1); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch4/nameseq.y: -------------------------------------------------------------------------------- 1 | %{ 2 | import static ch4.lexer.yylex; 3 | %} 4 | %token NAME NUMBER 5 | %% 6 | sequence : pair sequence | ; 7 | pair : NAME NUMBER ; 8 | %% 9 | -------------------------------------------------------------------------------- /ch4/nnws.l: -------------------------------------------------------------------------------- 1 | package ch4; 2 | %% 3 | %int 4 | %% 5 | [a-zA-Z]+ { return Parser.NAME; } 6 | [0-9]+ { return Parser.NUMBER; } 7 | [ \t]+ { } 8 | . { lexer.lexErr("unrecognized character"); } 9 | -------------------------------------------------------------------------------- /ch4/ns.y: -------------------------------------------------------------------------------- 1 | %token NAME NUMBER 2 | %% 3 | sequence : pair sequence | ; 4 | pair : NAME NUMBER ; 5 | %% 6 | -------------------------------------------------------------------------------- /ch4/ns_tab.icn: -------------------------------------------------------------------------------- 1 | class Parser(NAME, NUMBER) 2 | initially 3 | NAME := 257 4 | NUMBER := 258 5 | end 6 | -------------------------------------------------------------------------------- /ch4/parserTokens.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public interface parserTokens { 3 | public final static short BREAK=257; 4 | public final static short DOUBLE=258; 5 | public final static short ELSE=259; 6 | public final static short FOR=260; 7 | public final static short IF=261; 8 | public final static short INT=262; 9 | public final static short RETURN=263; 10 | public final static short VOID=264; 11 | public final static short WHILE=265; 12 | public final static short IDENTIFIER=266; 13 | public final static short CLASSNAME=267; 14 | public final static short CLASS=268; 15 | public final static short STRING=269; 16 | public final static short BOOL=270; 17 | public final static short INTLIT=271; 18 | public final static short DOUBLELIT=272; 19 | public final static short STRINGLIT=273; 20 | public final static short BOOLLIT=274; 21 | public final static short NULLVAL=275; 22 | public final static short LESSTHANOREQUAL=276; 23 | public final static short GREATERTHANOREQUAL=277; 24 | public final static short ISEQUALTO=278; 25 | public final static short NOTEQUALTO=279; 26 | public final static short LOGICALAND=280; 27 | public final static short LOGICALOR=281; 28 | public final static short INCREMENT=282; 29 | public final static short DECREMENT=283; 30 | public final static short PUBLIC=284; 31 | public final static short STATIC=285; 32 | } 33 | -------------------------------------------------------------------------------- /ch4/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: Parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch4; 6 | 7 | /** 8 | * BYACC/J Semantic Value for parser: Parser 9 | * This class provides some of the functionality 10 | * of the yacc/C 'union' directive 11 | */ 12 | public class ParserVal 13 | { 14 | /** 15 | * integer value of this 'union' 16 | */ 17 | public int ival; 18 | 19 | /** 20 | * double value of this 'union' 21 | */ 22 | public double dval; 23 | 24 | /** 25 | * string value of this 'union' 26 | */ 27 | public String sval; 28 | 29 | /** 30 | * object value of this 'union' 31 | */ 32 | public Object obj; 33 | 34 | //############################################# 35 | //## C O N S T R U C T O R S 36 | //############################################# 37 | /** 38 | * Initialize me without a value 39 | */ 40 | public ParserVal() 41 | { 42 | } 43 | /** 44 | * Initialize me as an int 45 | */ 46 | public ParserVal(int val) 47 | { 48 | ival=val; 49 | } 50 | 51 | /** 52 | * Initialize me as a double 53 | */ 54 | public ParserVal(double val) 55 | { 56 | dval=val; 57 | } 58 | 59 | /** 60 | * Initialize me as a string 61 | */ 62 | public ParserVal(String val) 63 | { 64 | sval=val; 65 | } 66 | 67 | /** 68 | * Initialize me as an Object 69 | */ 70 | public ParserVal(Object val) 71 | { 72 | obj=val; 73 | } 74 | }//end class 75 | 76 | //############################################# 77 | //## E N D O F F I L E 78 | //############################################# 79 | -------------------------------------------------------------------------------- /ch4/token.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public class token { 3 | public int cat; 4 | public String text; 5 | public int lineno; 6 | public token(int c, String s, int l) { 7 | cat = c; text = s; lineno = l; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch4/trivial.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | yyin := open(argv[1]) 3 | lexer := lexer() 4 | Parser := Parser() 5 | if yyparse() = 0 then write("No errors") 6 | end 7 | procedure yyerror(s) 8 | stop(s) 9 | end 10 | class lexer() 11 | method lexErr(s) 12 | stop("lexical error: ", s) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ch4/trivial.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public class trivial { 3 | static ch4.Parser par; 4 | public static void main(String argv[]) throws Exception { 5 | ch4.lexer.init(argv[0]); 6 | par = new ch4.Parser(); 7 | int i = par.yyparse(); 8 | if (i == 0) 9 | System.out.println("no errors"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch4/yyerror.icn: -------------------------------------------------------------------------------- 1 | procedure yyerror(s) 2 | stop(s) 3 | end 4 | -------------------------------------------------------------------------------- /ch4/yyerror.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public class yyerror { 3 | public static void yyerror(String s) { 4 | System.err.println(s); 5 | System.exit(1); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch5/cereal.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch5/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch5/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch5/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yylval, parser, yyfilename 2 | procedure main(argv) 3 | j0 := j0() 4 | serial := serial() 5 | parser := Parser() 6 | yyin := open(argv[1]) | stop("usage: j0 filename") 7 | yyfilename := argv[1] 8 | yylineno := 1 9 | if yyparse() = 0 then 10 | write("no errors") 11 | end 12 | class j0() 13 | method lexErr(s) 14 | stop(s, ": ", yytext) 15 | end 16 | method scan(cat) 17 | yylval := tree("token", cat, token(cat, yytext, yylineno)) 18 | return cat 19 | end 20 | method whitespace() 21 | end 22 | method newline() 23 | yylineno +:= 1 24 | end 25 | method comment() 26 | yytext ? { 27 | while tab(find("\n")+1) do newline() 28 | } 29 | end 30 | method ord(s) 31 | return proc("ord",0)(s[1]) 32 | end 33 | method print(root) 34 | root.print() 35 | root.print_graph(yyfilename || ".dot") 36 | end 37 | method node(s,r,p[]) 38 | return tree ! ([s,r] ||| p) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /ch5/j0.java: -------------------------------------------------------------------------------- 1 | package ch5; 2 | import java.io.FileReader; 3 | public class j0 { 4 | public static Yylex yylexer; 5 | public static ch5.parser par; 6 | public static void main(String argv[]) throws Exception { 7 | init(argv[0]); 8 | par = new ch5.parser(); 9 | // par.yydebug=true; 10 | yylineno = 1; 11 | int i = par.yyparse(); 12 | if (i == 0) 13 | System.out.println("no errors"); 14 | } 15 | public static int yylineno; 16 | public static String yyfilename; 17 | // public static parserVal yylval; 18 | public static void init(String s) throws Exception { 19 | yyfilename = s; 20 | yylexer = new Yylex(new FileReader(s)); 21 | } 22 | public static int YYEOF() { return Yylex.YYEOF; } 23 | public static int yylex() { 24 | int rv = 0; 25 | try { 26 | rv = yylexer.yylex(); 27 | } catch(java.io.IOException ioException) { 28 | rv = -1; 29 | } 30 | return rv; 31 | } 32 | public static String yytext() { 33 | return yylexer.yytext(); 34 | } 35 | public static void lexErr(String s) { 36 | System.err.println(s); 37 | System.exit(1); 38 | } 39 | public static int scan(int cat) { 40 | ch5.j0.par.yylval = 41 | new parserVal(new tree("token",0, 42 | new token(cat, yytext(), yylineno))); 43 | return cat; 44 | } 45 | public static void newline() { 46 | yylineno++; 47 | } 48 | public static void whitespace() { 49 | } 50 | public static void comment() { 51 | } 52 | public static short ord(String s) { return (short)(s.charAt(0)); } 53 | public static void print(parserVal root) { 54 | ((tree)root.obj).print(); 55 | ((tree)root.obj).print_graph(yyfilename + ".dot"); 56 | } 57 | public static tree unwrap(Object obj) { 58 | if (obj instanceof token) 59 | return new tree("token",0,(token)obj); 60 | else return (tree)obj; 61 | } 62 | public static parserVal node(String s,int r,parserVal...p) { 63 | tree[] t = new tree[p.length]; 64 | for(int i = 0; i < t.length; i++) 65 | t[i] = (tree)(p[i].obj); 66 | return new parserVal((Object)new tree(s,r,t)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ch5/j0gram_tab.icn: -------------------------------------------------------------------------------- 1 | class Parser(BREAK, DOUBLE, ELSE, FOR, IF, INT, RETURN, VOID, WHILE, IDENTIFIER, CLASSNAME, CLASS, STRING, BOOL, INTLIT, DOUBLELIT, STRINGLIT, BOOLLIT, NULLVAL, LESSTHANOREQUAL, GREATERTHANOREQUAL, ISEQUALTO, NOTEQUALTO, LOGICALAND, LOGICALOR, INCREMENT, DECREMENT, PUBLIC, STATIC) 2 | initially 3 | BREAK := 257 4 | DOUBLE := 258 5 | ELSE := 259 6 | FOR := 260 7 | IF := 261 8 | INT := 262 9 | RETURN := 263 10 | VOID := 264 11 | WHILE := 265 12 | IDENTIFIER := 266 13 | CLASSNAME := 267 14 | CLASS := 268 15 | STRING := 269 16 | BOOL := 270 17 | INTLIT := 271 18 | DOUBLELIT := 272 19 | STRINGLIT := 273 20 | BOOLLIT := 274 21 | NULLVAL := 275 22 | LESSTHANOREQUAL := 276 23 | GREATERTHANOREQUAL := 277 24 | ISEQUALTO := 278 25 | NOTEQUALTO := 279 26 | LOGICALAND := 280 27 | LOGICALOR := 281 28 | INCREMENT := 282 29 | DECREMENT := 283 30 | PUBLIC := 284 31 | STATIC := 285 32 | end 33 | -------------------------------------------------------------------------------- /ch5/javalex.l: -------------------------------------------------------------------------------- 1 | package ch5; 2 | %% 3 | %int 4 | id=([a-zA-Z_][a-zA-Z0-9_]*) 5 | %% 6 | "/*"([^*]|"*"+[^/*])*"*"+"/" { j0.comment(); } 7 | "//".*\r?\n { j0.comment(); } 8 | [ \t\r\f]+ { j0.whitespace(); } 9 | \n { j0.newline(); } 10 | "break" { return j0.scan(parser.BREAK); } 11 | "double" { return j0.scan(parser.DOUBLE); } 12 | "else" { return j0.scan(parser.ELSE); } 13 | "false" { return j0.scan(parser.BOOLLIT); } 14 | "for" { return j0.scan(parser.FOR); } 15 | "if" { return j0.scan(parser.IF); } 16 | "int" { return j0.scan(parser.INT); } 17 | "null" { return j0.scan(parser.NULLVAL); } 18 | "public" { return j0.scan(parser.PUBLIC); } 19 | "return" { return j0.scan(parser.RETURN); } 20 | "static" { return j0.scan(parser.STATIC); } 21 | "string" { return j0.scan(parser.STRING); } 22 | "true" { return j0.scan(parser.BOOLLIT); } 23 | "bool" { return j0.scan(parser.BOOL); } 24 | "void" { return j0.scan(parser.VOID); } 25 | "while" { return j0.scan(parser.WHILE); } 26 | "class" { return j0.scan(parser.CLASS); } 27 | "(" { return j0.scan(j0.ord("("));} 28 | ")" { return j0.scan(j0.ord(")"));} 29 | "[" { return j0.scan(j0.ord("["));} 30 | "]" { return j0.scan(j0.ord("]"));} 31 | "{" { return j0.scan(j0.ord("{"));} 32 | "}" { return j0.scan(j0.ord("}"));} 33 | ";" { return j0.scan(j0.ord(";"));} 34 | ":" { return j0.scan(j0.ord(":"));} 35 | "!" { return j0.scan(j0.ord("!"));} 36 | "*" { return j0.scan(j0.ord("*"));} 37 | "/" { return j0.scan(j0.ord("/"));} 38 | "%" { return j0.scan(j0.ord("%"));} 39 | "+" { return j0.scan(j0.ord("+"));} 40 | "-" { return j0.scan(j0.ord("-"));} 41 | "<" { return j0.scan(j0.ord("<"));} 42 | "<=" { return j0.scan(parser.LESSTHANOREQUAL);} 43 | ">" { return j0.scan(j0.ord(">"));} 44 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 45 | "==" { return j0.scan(parser.ISEQUALTO);} 46 | "!=" { return j0.scan(parser.NOTEQUALTO);} 47 | "&&" { return j0.scan(parser.LOGICALAND);} 48 | "||" { return j0.scan(parser.LOGICALOR);} 49 | "=" { return j0.scan(j0.ord("=")); } 50 | "+=" { return j0.scan(parser.INCREMENT); } 51 | "-=" { return j0.scan(parser.DECREMENT); } 52 | "," { return j0.scan(j0.ord(",")); } 53 | "." { return j0.scan(j0.ord(".")); } 54 | {id} { return j0.scan(parser.IDENTIFIER); } 55 | [0-9]+ { return j0.scan(parser.INTLIT); } 56 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 57 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 58 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 59 | . { j0.lexErr("unrecognized character"); } 60 | -------------------------------------------------------------------------------- /ch5/makefile: -------------------------------------------------------------------------------- 1 | all: java unicon 2 | 3 | LYU=javalex.u j0gram.u j0gram_tab.u 4 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) 5 | unicon: j0 6 | %.u : %.icn 7 | unicon -c $< 8 | j0: $(U) 9 | unicon $(U) 10 | javalex.icn: javalex.l 11 | uflex javalex.l 12 | j0gram.icn j0gram_tab.icn: j0gram.y 13 | iyacc -dd j0gram.y 14 | 15 | 16 | # A typical run might use 17 | # set CLASSPATH=".;c:\users\username\byopl" 18 | # in order to run from c:\users\username\byopl\ch5 19 | BYSRC=parser.java parserVal.java 20 | JSRC=j0.java Yylex.java token.java yyerror.java tree.java serial.java $(BYSRC) 21 | BYJOPTS= -Jclass=parser -Jpackage=ch5 22 | BYJIMPS= -Jyylex=ch5.j0.yylex -Jyyerror=ch5.yyerror.yyerror 23 | java: j0.class 24 | 25 | j: java 26 | java ch5.j0 hello.java 27 | dot -Tpng hello.java.dot >hello.png 28 | 29 | j0.class: $(JSRC) 30 | javac $(JSRC) 31 | parser.java parserVal.java: j0gram.y 32 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 33 | Yylex.java: javalex.l 34 | jflex javalex.l 35 | 36 | -------------------------------------------------------------------------------- /ch5/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch5; 6 | 7 | /** 8 | * BYACC/J Semantic Value for parser: parser 9 | * This class provides some of the functionality 10 | * of the yacc/C 'union' directive 11 | */ 12 | public class parserVal 13 | { 14 | /** 15 | * integer value of this 'union' 16 | */ 17 | public int ival; 18 | 19 | /** 20 | * double value of this 'union' 21 | */ 22 | public double dval; 23 | 24 | /** 25 | * string value of this 'union' 26 | */ 27 | public String sval; 28 | 29 | /** 30 | * object value of this 'union' 31 | */ 32 | public Object obj; 33 | 34 | //############################################# 35 | //## C O N S T R U C T O R S 36 | //############################################# 37 | /** 38 | * Initialize me without a value 39 | */ 40 | public parserVal() 41 | { 42 | } 43 | /** 44 | * Initialize me as an int 45 | */ 46 | public parserVal(int val) 47 | { 48 | ival=val; 49 | } 50 | 51 | /** 52 | * Initialize me as a double 53 | */ 54 | public parserVal(double val) 55 | { 56 | dval=val; 57 | } 58 | 59 | /** 60 | * Initialize me as a string 61 | */ 62 | public parserVal(String val) 63 | { 64 | sval=val; 65 | } 66 | 67 | /** 68 | * Initialize me as an Object 69 | */ 70 | public parserVal(Object val) 71 | { 72 | obj=val; 73 | } 74 | }//end class 75 | 76 | //############################################# 77 | //## E N D O F F I L E 78 | //############################################# 79 | -------------------------------------------------------------------------------- /ch5/prodrule.java: -------------------------------------------------------------------------------- 1 | public class prodrule { 2 | } 3 | -------------------------------------------------------------------------------- /ch5/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch5/serial.java: -------------------------------------------------------------------------------- 1 | package ch5; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch5/token.icn: -------------------------------------------------------------------------------- 1 | class token(cat, text, lineno, colno, ival, dval, sval) 2 | method deEscape(sin) 3 | local sout := "" 4 | sin := sin[2:-1] 5 | sin ? { 6 | while c := move(1) do { 7 | if c == "\\" then { 8 | if not (c := move(1)) then 9 | j0.lexErr("malformed string literal") 10 | else case c of { 11 | "t":{ sout ||:= "\t" } 12 | "n":{ sout ||:= "\n" } 13 | } 14 | } 15 | else sout ||:= c 16 | } 17 | } 18 | return sout 19 | end 20 | initially 21 | case cat of { 22 | parser.INTLIT: { ival := integer(text) } 23 | parser.DOUBLELIT: { dval := real(text) } 24 | parser.STRINGLIT: { sval := deEscape(text) } 25 | } 26 | end 27 | -------------------------------------------------------------------------------- /ch5/token.java: -------------------------------------------------------------------------------- 1 | package ch5; 2 | public class token { 3 | public int id; 4 | public int cat; 5 | public String text; 6 | public int lineno; 7 | public token(int c, String s, int l) { 8 | cat = c; text = s; lineno = l; 9 | id = serial.getid(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch5/tree.icn: -------------------------------------------------------------------------------- 1 | class tree (id,sym,rule,nkids,tok,kids) 2 | method print(level:0) 3 | writes(repl(" ",level)) 4 | if \tok then { 5 | write(id, " ", tok.text, " (",tok.cat, "): ",tok.lineno) 6 | } 7 | else { 8 | write(id, " ", sym, " (", rule, "): ", nkids) 9 | every (!kids).print(level+1) 10 | } 11 | end 12 | method print_graph(fw) 13 | if type(fw) == "string" then { 14 | fw := open(fw, "w") | 15 | stop("can't open ", image(fw), " for writing") 16 | write(fw, "digraph {") 17 | print_graph(fw) 18 | write(fw, "}") 19 | close(fw) 20 | } 21 | else if \tok then print_leaf(fw) 22 | else { 23 | print_branch(fw) 24 | every i := 1 to nkids do 25 | if \kids[i] then { 26 | write(fw, "N",id," -> N",kids[i].id,";") 27 | kids[i].print_graph(fw) 28 | } else { 29 | write(fw, "N",id," -> N",id,"_",j,";") 30 | write(fw, "N", id, "_", j, 31 | " [label=\"Empty rule\"];") 32 | j +:= 1 33 | } 34 | } 35 | end 36 | method print_leaf(pw) 37 | local s := yyname[tok.cat] 38 | print_branch(pw) 39 | write(pw,"N",id, 40 | " [shape=box style=dotted label=\" ",s," \\n ") 41 | write(pw,"text = ",escape(tok.text)," \\l lineno = ", 42 | tok.lineno," \\l\"];\n") 43 | end 44 | method print_branch(pw) 45 | write(pw, "N",id," [shape=box label=\"", 46 | pretty_print_name(),"\"];\n"); 47 | end 48 | method escape(s) 49 | if s[1] == "\"" then 50 | return "\\" || s[1:-1] || "\\\"" 51 | else return s 52 | end 53 | method pretty_print_name() 54 | if /tok then return sym || "#" || (rule%10) 55 | else return escape(tok.text) || ":" || tok.cat 56 | end 57 | 58 | initially (s,r,x[]) 59 | id := serial.getid(); sym := s; rule := r 60 | if type(x[1]) == "token__state" then { 61 | nkids := 0; tok := x[1] 62 | } else { 63 | nkids := *x; 64 | kids := x 65 | } 66 | end 67 | -------------------------------------------------------------------------------- /ch5/tree.java: -------------------------------------------------------------------------------- 1 | package ch5; 2 | import java.io.PrintWriter; 3 | import java.io.BufferedWriter; 4 | import java.io.FileWriter; 5 | class tree { 6 | int id; 7 | String sym; 8 | int rule; 9 | int nkids; 10 | token tok; 11 | tree kids[]; 12 | 13 | public String escape(String s) { 14 | if (s.charAt(0) == '\"') 15 | return "\\"+s.substring(0, s.length()-1)+"\\\""; 16 | else return s; 17 | } 18 | 19 | public String pretty_print_name() { 20 | if (tok == null) return sym +"#"+(rule%10); 21 | else { 22 | return escape(tok.text)+":"+tok.cat; 23 | } 24 | } 25 | 26 | void print_graph(String filename){ 27 | try { 28 | PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(filename))); 29 | pw.printf("digraph {\n"); 30 | j = 0; 31 | print_graph(pw); 32 | pw.printf("}\n"); 33 | pw.close(); 34 | } 35 | catch (java.io.IOException ioException) { 36 | System.err.println("printgraph exception"); 37 | System.exit(1); 38 | } 39 | } 40 | 41 | int j; 42 | void print_graph(PrintWriter pw) { 43 | int i; 44 | if (tok != null) { 45 | print_leaf(pw); 46 | return; 47 | } 48 | // from here on out, we know we are not a leaf 49 | print_branch(pw); 50 | 51 | for(i=0; i N%d;\n", id, kids[i].id); 54 | kids[i].print_graph(pw); 55 | } else { 56 | pw.printf("N%d -> N%d_%d;\n", id, id, j); 57 | pw.printf("N%d%d [label=\"%s\"];\n", id, j, "Empty rule"); 58 | j++; 59 | } 60 | } 61 | } 62 | 63 | void print_leaf(PrintWriter pw) { 64 | String s = parser.yyname[tok.cat]; 65 | print_branch(pw); 66 | pw.printf("N%d [shape=box style=dotted label=\" %s \\n ", id, s, tok.cat); 67 | pw.printf("text = %s \\l lineno = %d \\l\"];\n", 68 | escape(tok.text), tok.lineno); 69 | } 70 | 71 | void print_branch(PrintWriter pw) { 72 | pw.printf("N%d ",id); 73 | pw.printf("[shape=box label=\"%s",pretty_print_name()); 74 | if (tok != null) 75 | pw.printf("struct token* leaf %d", tok.id); 76 | pw.printf("\"];\n"); 77 | } 78 | 79 | public void print(int level) { 80 | int i; 81 | for(i=0;i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch6/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch6/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch6/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yycolno, yylval, parser, global_st 2 | procedure main(argv) 3 | j0 := j0() 4 | serial := serial() 5 | parser := Parser() 6 | yyin := open(argv[1]) | stop("usage: j0 filename") 7 | yylineno := yycolno := 1 8 | if yyparse() = 0 then 9 | write("no errors") 10 | end 11 | class j0() 12 | method lexErr(s) 13 | stop(s, ": ", yytext) 14 | end 15 | method scan(cat) 16 | yylval := tree("token", cat, token(cat, yytext, yylineno, yycolno)) 17 | yycolno +:= *yytext 18 | return cat 19 | end 20 | method whitespace() 21 | yycolno +:= *yytext 22 | end 23 | method newline() 24 | yylineno +:= 1; yycolno := 1 25 | end 26 | method comment() 27 | yytext ? { 28 | while tab(find("\n")+1) do newline() 29 | yycolno +:= *tab(0) 30 | } 31 | end 32 | method ord(s) 33 | return proc("ord",0)(s[1]) 34 | end 35 | method print(root) 36 | root.print() 37 | end 38 | method node(s,r,p[]) 39 | return tree ! ([s,r] ||| p) 40 | end 41 | method semantic(root) 42 | local out_st, System_st 43 | global_st := symtab("global") 44 | System_st := symtab("class") 45 | out_st := symtab("class") 46 | out_st.insert("println", false) 47 | System_st.insert("out", false, out_st) 48 | global_st.insert("System", false, System_st) 49 | root.mkSymTables(global_st) 50 | root.populateSymTables() 51 | root.checkSymTables() 52 | global_st.print() 53 | end 54 | method semerror(s) 55 | stop("semantic error: ", s) 56 | end 57 | 58 | end 59 | -------------------------------------------------------------------------------- /ch6/j0.java: -------------------------------------------------------------------------------- 1 | package ch6; 2 | import java.io.FileReader; 3 | public class j0 { 4 | public static Yylex yylexer; 5 | public static ch6.parser par; 6 | public static ch6.symtab global_st; 7 | public static void main(String argv[]) throws Exception { 8 | init(argv[0]); 9 | par = new ch6.parser(); 10 | // par.yydebug=true; 11 | yylineno = 1; 12 | int i = par.yyparse(); 13 | if (i == 0) 14 | System.out.println("no errors"); 15 | } 16 | public static int yylineno; 17 | public static String yyfilename; 18 | // public static parserVal yylval; 19 | public static void init(String s) throws Exception { 20 | yyfilename = s; 21 | System.out.println("yyfilename "+yyfilename); 22 | yylexer = new Yylex(new FileReader(s)); 23 | } 24 | public static int YYEOF() { return Yylex.YYEOF; } 25 | public static int yylex() { 26 | int rv = 0; 27 | try { 28 | rv = yylexer.yylex(); 29 | } catch(java.io.IOException ioException) { 30 | rv = -1; 31 | } 32 | return rv; 33 | } 34 | public static String yytext() { 35 | return yylexer.yytext(); 36 | } 37 | public static void lexErr(String s) { 38 | System.err.println(s); 39 | System.exit(1); 40 | } 41 | public static int scan(int cat) { 42 | ch6.j0.par.yylval = 43 | new parserVal(new tree("token",0, 44 | new token(cat, yytext(), yylineno))); 45 | return cat; 46 | } 47 | public static void newline() { 48 | yylineno++; 49 | } 50 | public static void whitespace() { 51 | } 52 | public static void comment() { 53 | } 54 | public static short ord(String s) { return (short)(s.charAt(0)); } 55 | public static void print(parserVal root) { 56 | ((tree)root.obj).print_graph(yyfilename + ".dot"); 57 | } 58 | public static tree unwrap(Object obj) { 59 | if (obj instanceof token) 60 | return new tree("token",0,(token)obj); 61 | else return (tree)obj; 62 | } 63 | public static parserVal node(String s,int r,parserVal...p) { 64 | tree[] t = new tree[p.length]; 65 | for(int i = 0; i < t.length; i++) 66 | t[i] = (tree)(p[i].obj); 67 | return new parserVal((Object)new tree(s,r,t)); 68 | } 69 | public static void semantic(parserVal r) { 70 | tree root = (tree)(r.obj); 71 | ch6.symtab out_st, System_st; 72 | global_st = new ch6.symtab("global"); 73 | System_st = new ch6.symtab("class"); 74 | out_st = new ch6.symtab("class"); 75 | out_st.insert("println", false); 76 | System_st.insert("out", false, out_st); 77 | global_st.insert("System", false, System_st); 78 | root.mkSymTables(global_st); 79 | root.populateSymTables(); 80 | root.checkSymTables(); 81 | global_st.print(); 82 | } 83 | public static void semerror(String s) { 84 | System.out.println("semantic error: " + s); 85 | System.exit(1); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ch6/javalex.l: -------------------------------------------------------------------------------- 1 | package ch6; 2 | %% 3 | %int 4 | id=([a-zA-Z_][a-zA-Z0-9_]*) 5 | %% 6 | "/*"([^*]|"*"+[^/*])*"*"+"/" { j0.comment(); } 7 | "//".*\r?\n { j0.comment(); } 8 | [ \t\r\f]+ { j0.whitespace(); } 9 | \n { j0.newline(); } 10 | "break" { return j0.scan(parser.BREAK); } 11 | "double" { return j0.scan(parser.DOUBLE); } 12 | "else" { return j0.scan(parser.ELSE); } 13 | "false" { return j0.scan(parser.BOOLLIT); } 14 | "for" { return j0.scan(parser.FOR); } 15 | "if" { return j0.scan(parser.IF); } 16 | "int" { return j0.scan(parser.INT); } 17 | "null" { return j0.scan(parser.NULLVAL); } 18 | "public" { return j0.scan(parser.PUBLIC); } 19 | "return" { return j0.scan(parser.RETURN); } 20 | "static" { return j0.scan(parser.STATIC); } 21 | "string" { return j0.scan(parser.STRING); } 22 | "true" { return j0.scan(parser.BOOLLIT); } 23 | "bool" { return j0.scan(parser.BOOL); } 24 | "void" { return j0.scan(parser.VOID); } 25 | "while" { return j0.scan(parser.WHILE); } 26 | "class" { return j0.scan(parser.CLASS); } 27 | "(" { return j0.scan(j0.ord("("));} 28 | ")" { return j0.scan(j0.ord(")"));} 29 | "[" { return j0.scan(j0.ord("["));} 30 | "]" { return j0.scan(j0.ord("]"));} 31 | "{" { return j0.scan(j0.ord("{"));} 32 | "}" { return j0.scan(j0.ord("}"));} 33 | ";" { return j0.scan(j0.ord(";"));} 34 | ":" { return j0.scan(j0.ord(":"));} 35 | "!" { return j0.scan(j0.ord("!"));} 36 | "*" { return j0.scan(j0.ord("*"));} 37 | "/" { return j0.scan(j0.ord("/"));} 38 | "%" { return j0.scan(j0.ord("%"));} 39 | "+" { return j0.scan(j0.ord("+"));} 40 | "-" { return j0.scan(j0.ord("-"));} 41 | "<" { return j0.scan(j0.ord("<"));} 42 | "<=" { return j0.scan(parser.LESSTHANOREQUAL);} 43 | ">" { return j0.scan(j0.ord(">"));} 44 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 45 | "==" { return j0.scan(parser.ISEQUALTO);} 46 | "!=" { return j0.scan(parser.NOTEQUALTO);} 47 | "&&" { return j0.scan(parser.LOGICALAND);} 48 | "||" { return j0.scan(parser.LOGICALOR);} 49 | "=" { return j0.scan(j0.ord("=")); } 50 | "+=" { return j0.scan(parser.INCREMENT); } 51 | "-=" { return j0.scan(parser.DECREMENT); } 52 | "," { return j0.scan(j0.ord(",")); } 53 | "." { return j0.scan(j0.ord(".")); } 54 | {id} { return j0.scan(parser.IDENTIFIER); } 55 | [0-9]+ { return j0.scan(parser.INTLIT); } 56 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 57 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 58 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 59 | . { j0.lexErr("unrecognized character"); } 60 | -------------------------------------------------------------------------------- /ch6/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u 6 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) 7 | unicon: j0 8 | %.u : %.icn 9 | unicon -c $< 10 | j0: $(U) 11 | unicon $(U) 12 | javalex.icn: javalex.l 13 | uflex javalex.l 14 | j0gram.icn j0gram_tab.icn: j0gram.y 15 | iyacc -dd j0gram.y 16 | 17 | # A typical run might use 18 | # set CLASSPATH=".;c:\users\username\byopl" 19 | # in order to run from c:\users\username\byopl\ch5 20 | LYSRC=Yylex.java parser.java parserVal.java 21 | STJ=symtab.java symtab_entry.java 22 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) 23 | BYJOPTS= -Jclass=parser -Jpackage=ch6 24 | BYJIMPS= -Jyylex=ch6.j0.yylex -Jyyerror=ch6.yyerror.yyerror 25 | java: j0.class 26 | 27 | j: java 28 | java ch6.j0 hello.java 29 | dot -Tpng hello.java.dot >hello.png 30 | 31 | j0.class: $(JSRC) 32 | javac $(JSRC) 33 | parser.java parserVal.java: j0gram.y 34 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 35 | Yylex.java: javalex.l 36 | jflex javalex.l 37 | 38 | -------------------------------------------------------------------------------- /ch6/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch6/serial.java: -------------------------------------------------------------------------------- 1 | package ch6; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch6/symtab.icn: -------------------------------------------------------------------------------- 1 | class symtab(scope, parent, t) 2 | method lookup(s) 3 | return \ (t[s]) 4 | end 5 | method insert(s, isConst, sub) 6 | if \ (t[s]) then j0.semerror("redeclaration of " || s) 7 | else t[s] := symtab_entry(s, self, sub, isConst) 8 | end 9 | method print(level:0) 10 | writes(repl(" ",level)) 11 | write(scope, " - ", *t, " symbols") 12 | every (!t).print(level+1); 13 | end 14 | 15 | initially 16 | t := table() 17 | end 18 | -------------------------------------------------------------------------------- /ch6/symtab.java: -------------------------------------------------------------------------------- 1 | package ch6; 2 | import java.util.HashMap; 3 | public class symtab { 4 | String scope; 5 | symtab parent; 6 | HashMap t; 7 | symtab(String sc) { 8 | scope = sc; 9 | t = new HashMap(); 10 | } 11 | symtab(String sc, symtab p) { 12 | scope = sc; parent = p; 13 | t = new HashMap(); 14 | } 15 | symtab_entry lookup(String s) { 16 | return t.get(s); 17 | } 18 | void insert(String s, Boolean iC, symtab sub) { 19 | if (t.containsKey(s)) { 20 | j0.semerror("redeclaration of " + s); 21 | } else { 22 | sub.parent = this; 23 | t.put(s, new symtab_entry(s, this, iC, sub)); 24 | } 25 | } 26 | void insert(String s, Boolean iC) { 27 | if (t.containsKey(s)) { 28 | j0.semerror("redeclaration of " + s); 29 | } else { 30 | t.put(s, new symtab_entry(s, this, iC)); 31 | } 32 | } 33 | void print() { print(0); } 34 | void print(int level) { 35 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch7/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | public class arraytype extends typeinfo { 3 | typeinfo element_type; 4 | public arraytype(typeinfo t) { 5 | basetype = "array"; element_type = t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch7/classtype.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | public class classtype extends typeinfo { 3 | String name; 4 | symtab st; 5 | parameter [] methods; 6 | parameter [] fields; 7 | typeinfo [] constrs; 8 | public classtype(String s) { name = s; } 9 | public classtype(String s, symtab stab) { name = s; st = stab; } 10 | } 11 | -------------------------------------------------------------------------------- /ch7/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | int x; 4 | x = 0; 5 | x = x + "hello"; 6 | System.out.println("hello, jzero!"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ch7/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch7/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yycolno, yylval, parser, global_st 2 | procedure main(argv) 3 | j0 := j0() 4 | serial := serial() 5 | parser := Parser() 6 | yyin := open(argv[1]) | stop("usage: j0 filename") 7 | yylineno := yycolno := 1 8 | if yyparse() = 0 then 9 | write("no errors") 10 | end 11 | class j0() 12 | method lexErr(s) 13 | stop(s, ": ", yytext) 14 | end 15 | method scan(cat) 16 | yylval := tree("token", cat, token(cat, yytext, yylineno, yycolno)) 17 | yycolno +:= *yytext 18 | return cat 19 | end 20 | method whitespace() 21 | yycolno +:= *yytext 22 | end 23 | method newline() 24 | yylineno +:= 1; yycolno := 1 25 | end 26 | method comment() 27 | yytext ? { 28 | while tab(find("\n")+1) do newline() 29 | yycolno +:= *tab(0) 30 | } 31 | end 32 | method ord(s) 33 | return proc("ord",0)(s[1]) 34 | end 35 | method print(root) 36 | root.print() 37 | end 38 | method node(s,r,p[]) 39 | rv := tree ! ([s,r] ||| p) 40 | return rv 41 | end 42 | method semantic(root) 43 | local out_st, System_st 44 | global_st := symtab("global") 45 | System_st := symtab("class") 46 | out_st := symtab("class") 47 | out_st.insert("println", false, , methodtype()) 48 | System_st.insert("out", false, out_st, classtype("PrintStream",out_st)) 49 | global_st.insert("System", false, System_st, classtype("System",System_st)) 50 | root.mkSymTables(global_st) 51 | root.populateSymTables() 52 | root.checkSymTables() 53 | # global_st.print() 54 | root.checktype() 55 | end 56 | method semerror(s) 57 | stop("semantic error: ", s) 58 | end 59 | method calctype(t) 60 | t.kids[1].calctype() 61 | t.kids[2].assigntype(t.kids[1].typ) 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /ch7/j0.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | import java.io.FileReader; 3 | public class j0 { 4 | public static Yylex yylexer; 5 | public static ch7.parser par; 6 | public static ch7.symtab global_st; 7 | public static void main(String argv[]) throws Exception { 8 | init(argv[0]); 9 | par = new ch7.parser(); 10 | // par.yydebug=true; 11 | yylineno = 1; 12 | int i = par.yyparse(); 13 | if (i == 0) 14 | System.out.println("no errors"); 15 | } 16 | public static int yylineno; 17 | public static String yyfilename; 18 | // public static parserVal yylval; 19 | public static void init(String s) throws Exception { 20 | yyfilename = s; 21 | System.out.println("yyfilename "+yyfilename); 22 | yylexer = new Yylex(new FileReader(s)); 23 | } 24 | public static int YYEOF() { return Yylex.YYEOF; } 25 | public static int yylex() { 26 | int rv = 0; 27 | try { 28 | rv = yylexer.yylex(); 29 | } catch(java.io.IOException ioException) { 30 | rv = -1; 31 | } 32 | return rv; 33 | } 34 | public static String yytext() { 35 | return yylexer.yytext(); 36 | } 37 | public static void lexErr(String s) { 38 | System.err.println(s); 39 | System.exit(1); 40 | } 41 | public static int scan(int cat) { 42 | ch7.j0.par.yylval = 43 | new parserVal(new tree("token",0, 44 | new token(cat, yytext(), yylineno))); 45 | return cat; 46 | } 47 | public static void newline() { 48 | yylineno++; 49 | } 50 | public static void whitespace() { 51 | } 52 | public static void comment() { 53 | } 54 | public static short ord(String s) { return (short)(s.charAt(0)); } 55 | public static void print(parserVal root) { 56 | ((tree)root.obj).print_graph(yyfilename + ".dot"); 57 | } 58 | public static tree unwrap(Object obj) { 59 | if (obj instanceof token) 60 | return new tree("token",0,(token)obj); 61 | else return (tree)obj; 62 | } 63 | public static parserVal node(String s,int r,parserVal...p) { 64 | tree[] t = new tree[p.length]; 65 | for(int i = 0; i < t.length; i++) 66 | t[i] = (tree)(p[i].obj); 67 | return new parserVal((Object)new tree(s,r,t)); 68 | } 69 | public static void semantic(parserVal r) { 70 | tree root = (tree)(r.obj); 71 | ch7.symtab out_st, System_st; 72 | global_st = new ch7.symtab("global"); 73 | System_st = new ch7.symtab("class"); 74 | out_st = new ch7.symtab("class"); 75 | out_st.insert("println", false, null, new methodtype(null, null)); 76 | System_st.insert("out", false, out_st, 77 | new classtype("PrintStream",out_st)); 78 | global_st.insert("System", false, System_st, 79 | new classtype("System",System_st)); 80 | root.mkSymTables(global_st); 81 | root.populateSymTables(); 82 | root.checkSymTables(); 83 | // global_st.print(); 84 | root.checktype(false); 85 | } 86 | public static void semerror(String s) { 87 | System.out.println("semantic error: " + s); 88 | System.exit(1); 89 | } 90 | public static void calctype(parserVal pv){ 91 | tree t = (tree)pv.obj; 92 | t.kids[0].calctype(); 93 | t.kids[1].assigntype(t.kids[0].typ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ch7/j0gram_tab.icn: -------------------------------------------------------------------------------- 1 | class Parser(BREAK, DOUBLE, ELSE, FOR, IF, INT, RETURN, VOID, WHILE, IDENTIFIER, CLASSNAME, CLASS, STRING, BOOL, INTLIT, DOUBLELIT, STRINGLIT, BOOLLIT, NULLVAL, LESSTHANOREQUAL, GREATERTHANOREQUAL, ISEQUALTO, NOTEQUALTO, LOGICALAND, LOGICALOR, INCREMENT, DECREMENT, PUBLIC, STATIC) 2 | initially 3 | BREAK := 257 4 | DOUBLE := 258 5 | ELSE := 259 6 | FOR := 260 7 | IF := 261 8 | INT := 262 9 | RETURN := 263 10 | VOID := 264 11 | WHILE := 265 12 | IDENTIFIER := 266 13 | CLASSNAME := 267 14 | CLASS := 268 15 | STRING := 269 16 | BOOL := 270 17 | INTLIT := 271 18 | DOUBLELIT := 272 19 | STRINGLIT := 273 20 | BOOLLIT := 274 21 | NULLVAL := 275 22 | LESSTHANOREQUAL := 276 23 | GREATERTHANOREQUAL := 277 24 | ISEQUALTO := 278 25 | NOTEQUALTO := 279 26 | LOGICALAND := 280 27 | LOGICALOR := 281 28 | INCREMENT := 282 29 | DECREMENT := 283 30 | PUBLIC := 284 31 | STATIC := 285 32 | end 33 | -------------------------------------------------------------------------------- /ch7/javalex.l: -------------------------------------------------------------------------------- 1 | package ch7; 2 | %% 3 | %int 4 | id=([a-zA-Z_][a-zA-Z0-9_]*) 5 | %% 6 | "/*"([^*]|"*"+[^/*])*"*"+"/" { j0.comment(); } 7 | "//".*\r?\n { j0.comment(); } 8 | [ \t\r\f]+ { j0.whitespace(); } 9 | \n { j0.newline(); } 10 | "break" { return j0.scan(parser.BREAK); } 11 | "double" { return j0.scan(parser.DOUBLE); } 12 | "else" { return j0.scan(parser.ELSE); } 13 | "false" { return j0.scan(parser.BOOLLIT); } 14 | "for" { return j0.scan(parser.FOR); } 15 | "if" { return j0.scan(parser.IF); } 16 | "int" { return j0.scan(parser.INT); } 17 | "null" { return j0.scan(parser.NULLVAL); } 18 | "public" { return j0.scan(parser.PUBLIC); } 19 | "return" { return j0.scan(parser.RETURN); } 20 | "static" { return j0.scan(parser.STATIC); } 21 | "string" { return j0.scan(parser.STRING); } 22 | "true" { return j0.scan(parser.BOOLLIT); } 23 | "bool" { return j0.scan(parser.BOOL); } 24 | "void" { return j0.scan(parser.VOID); } 25 | "while" { return j0.scan(parser.WHILE); } 26 | "class" { return j0.scan(parser.CLASS); } 27 | "(" { return j0.scan(j0.ord("("));} 28 | ")" { return j0.scan(j0.ord(")"));} 29 | "[" { return j0.scan(j0.ord("["));} 30 | "]" { return j0.scan(j0.ord("]"));} 31 | "{" { return j0.scan(j0.ord("{"));} 32 | "}" { return j0.scan(j0.ord("}"));} 33 | ";" { return j0.scan(j0.ord(";"));} 34 | ":" { return j0.scan(j0.ord(":"));} 35 | "!" { return j0.scan(j0.ord("!"));} 36 | "*" { return j0.scan(j0.ord("*"));} 37 | "/" { return j0.scan(j0.ord("/"));} 38 | "%" { return j0.scan(j0.ord("%"));} 39 | "+" { return j0.scan(j0.ord("+"));} 40 | "-" { return j0.scan(j0.ord("-"));} 41 | "<" { return j0.scan(j0.ord("<"));} 42 | "<=" { return j0.scan(parser.LESSTHANOREQUAL);} 43 | ">" { return j0.scan(j0.ord(">"));} 44 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 45 | "==" { return j0.scan(parser.ISEQUALTO);} 46 | "!=" { return j0.scan(parser.NOTEQUALTO);} 47 | "&&" { return j0.scan(parser.LOGICALAND);} 48 | "||" { return j0.scan(parser.LOGICALOR);} 49 | "=" { return j0.scan(j0.ord("=")); } 50 | "+=" { return j0.scan(parser.INCREMENT); } 51 | "-=" { return j0.scan(parser.DECREMENT); } 52 | "," { return j0.scan(j0.ord(",")); } 53 | "." { return j0.scan(j0.ord(".")); } 54 | {id} { return j0.scan(parser.IDENTIFIER); } 55 | [0-9]+ { return j0.scan(parser.INTLIT); } 56 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 57 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 58 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 59 | . { j0.lexErr("unrecognized character"); } 60 | -------------------------------------------------------------------------------- /ch7/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u typeinfo.u 6 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) 7 | unicon: j0 8 | %.u : %.icn 9 | unicon -c $< 10 | j0: $(U) 11 | unicon $(U) 12 | javalex.icn: javalex.l 13 | uflex javalex.l 14 | j0gram.icn j0gram_tab.icn: j0gram.y 15 | iyacc -dd j0gram.y 16 | 17 | # A typical run might use 18 | # set CLASSPATH=".;c:\users\username\byopl" 19 | # in order to run from c:\users\username\byopl\ch7 20 | LYSRC=Yylex.java parser.java parserVal.java 21 | TPJ=typeinfo.java arraytype.java classtype.java methodtype.java parameter.java 22 | STJ=symtab.java symtab_entry.java $(TPJ) 23 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) 24 | BYJOPTS= -Jclass=parser -Jpackage=ch7 25 | BYJIMPS= -Jyylex=ch7.j0.yylex -Jyyerror=ch7.yyerror.yyerror 26 | java: j0.class 27 | 28 | j: java 29 | java ch7.j0 hello.java 30 | dot -Tpng hello.java.dot >hello.png 31 | 32 | j0.class: $(JSRC) 33 | javac $(JSRC) 34 | parser.java parserVal.java: j0gram.y 35 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 36 | Yylex.java: javalex.l 37 | jflex javalex.l 38 | 39 | -------------------------------------------------------------------------------- /ch7/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | public class methodtype extends typeinfo { 3 | parameter [] parameters; 4 | typeinfo return_type; 5 | methodtype(parameter [] p, typeinfo rt){ 6 | parameters = p; return_type = rt; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ch7/parameter.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch7/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch7; 6 | 7 | /** 8 | * BYACC/J Semantic Value for parser: parser 9 | * This class provides some of the functionality 10 | * of the yacc/C 'union' directive 11 | */ 12 | public class parserVal 13 | { 14 | /** 15 | * integer value of this 'union' 16 | */ 17 | public int ival; 18 | 19 | /** 20 | * double value of this 'union' 21 | */ 22 | public double dval; 23 | 24 | /** 25 | * string value of this 'union' 26 | */ 27 | public String sval; 28 | 29 | /** 30 | * object value of this 'union' 31 | */ 32 | public Object obj; 33 | 34 | //############################################# 35 | //## C O N S T R U C T O R S 36 | //############################################# 37 | /** 38 | * Initialize me without a value 39 | */ 40 | public parserVal() 41 | { 42 | } 43 | /** 44 | * Initialize me as an int 45 | */ 46 | public parserVal(int val) 47 | { 48 | ival=val; 49 | } 50 | 51 | /** 52 | * Initialize me as a double 53 | */ 54 | public parserVal(double val) 55 | { 56 | dval=val; 57 | } 58 | 59 | /** 60 | * Initialize me as a string 61 | */ 62 | public parserVal(String val) 63 | { 64 | sval=val; 65 | } 66 | 67 | /** 68 | * Initialize me as an Object 69 | */ 70 | public parserVal(Object val) 71 | { 72 | obj=val; 73 | } 74 | }//end class 75 | 76 | //############################################# 77 | //## E N D O F F I L E 78 | //############################################# 79 | -------------------------------------------------------------------------------- /ch7/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch7/serial.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch7/symtab.icn: -------------------------------------------------------------------------------- 1 | class symtab(scope, parent, t) 2 | method lookup(s) 3 | return if rv := \ (t[s]) then { 4 | rv } 5 | else { 6 | (\parent).lookup(s) 7 | } 8 | end 9 | method insert(s, isConst, sub, typ) 10 | if \ (t[s]) then j0.semerror("redeclaration of " || s) 11 | else { (\sub).parent := self 12 | t[s] := symtab_entry(s, self, sub, isConst, typ) } 13 | end 14 | method print(level:0) 15 | writes(repl(" ",level)) 16 | write(scope, " - ", *t, " symbols") 17 | every (!t).print(level+1); 18 | end 19 | 20 | initially 21 | t := table() 22 | end 23 | -------------------------------------------------------------------------------- /ch7/symtab.java: -------------------------------------------------------------------------------- 1 | package ch7; 2 | import java.util.HashMap; 3 | public class symtab { 4 | String scope; 5 | symtab parent; 6 | HashMap t; 7 | symtab(String sc) { 8 | scope = sc; 9 | t = new HashMap(); 10 | } 11 | symtab(String sc, symtab p) { 12 | scope = sc; parent = p; 13 | t = new HashMap(); 14 | } 15 | symtab_entry lookup(String s) { 16 | symtab_entry rv; 17 | rv = t.get(s); 18 | if (rv != null) { 19 | return rv; 20 | } 21 | if (parent != null) return parent.lookup(s); 22 | return null; 23 | } 24 | void insert(String s, Boolean iC, symtab sub, typeinfo typ) { 25 | if (t.containsKey(s)) { 26 | j0.semerror("redeclaration of " + s); 27 | } else { 28 | if (sub != null) 29 | sub.parent = this; 30 | t.put(s, new symtab_entry(s, this, iC, sub, typ)); 31 | } 32 | } 33 | void insert(String s, Boolean iC) { 34 | if (t.containsKey(s)) { 35 | j0.semerror("redeclaration of " + s); 36 | } else { 37 | t.put(s, new symtab_entry(s, this, iC)); 38 | } 39 | } 40 | void print() { print(0); } 41 | void print(int level) { 42 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch8/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | public class arraytype extends typeinfo { 3 | typeinfo element_type; 4 | public String str() { 5 | return "array of " + (element_type!=null?element_type.str():"undef"); 6 | } 7 | public arraytype(typeinfo t) { 8 | basetype = "array"; element_type = t; } 9 | } 10 | -------------------------------------------------------------------------------- /ch8/arrtst.java: -------------------------------------------------------------------------------- 1 | public class arrtst { 2 | public static void main(String argv[]) { 3 | int x[]; 4 | x = new int[3]; 5 | x[1] = 0; 6 | x[0] = x[1]; 7 | x[2] = argv[1]; 8 | System.out.println("hello, world"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch8/classtype.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | public class classtype extends typeinfo { 3 | String name; 4 | symtab st; 5 | parameter [] methods; 6 | parameter [] fields; 7 | typeinfo [] constrs; 8 | public String str() { 9 | return name; 10 | } 11 | public classtype(String s) { name = s; basetype="class";} 12 | public classtype(String s, symtab stab) { name = s; st = stab; basetype="class";} 13 | public classtype(String s, symtab stab, 14 | parameter []ms, parameter[]fs, typeinfo[]cs) { 15 | name = s; st = stab; methods=ms; fields=fs; constrs=cs; basetype="class";} 16 | } 17 | -------------------------------------------------------------------------------- /ch8/clstest.java: -------------------------------------------------------------------------------- 1 | public class clstest { 2 | public static void main(String argv[]) { 3 | clstest c; 4 | c = new clstest(); 5 | System.out.println("hello, jzero!"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch8/funtest.java: -------------------------------------------------------------------------------- 1 | public class funtest { 2 | public static int foo(int x, int y, String z) { 3 | return 0; 4 | } 5 | public static void main(String argv[]) { 6 | int x; 7 | x = foo(0,1,"howdy"); 8 | x = x + 1; 9 | System.out.println("hello, jzero!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch8/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | int x; 4 | x = 0; 5 | x = x + "hello"; 6 | System.out.println("hello, jzero!"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ch8/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yycolno, yylval, parser, global_st 2 | procedure main(argv) 3 | j0 := j0() 4 | serial := serial() 5 | parser := Parser() 6 | yyin := open(argv[1]) | stop("usage: j0 filename") 7 | yylineno := yycolno := 1 8 | if yyparse() = 0 then 9 | write("no errors") 10 | end 11 | class j0() 12 | method lexErr(s) 13 | stop(s, ": ", yytext) 14 | end 15 | method scan(cat) 16 | yylval := tree("token", cat, token(cat, yytext, yylineno, yycolno)) 17 | yycolno +:= *yytext 18 | return cat 19 | end 20 | method whitespace() 21 | yycolno +:= *yytext 22 | end 23 | method newline() 24 | yylineno +:= 1; yycolno := 1 25 | end 26 | method comment() 27 | yytext ? { 28 | while tab(find("\n")+1) do newline() 29 | yycolno +:= *tab(0) 30 | } 31 | end 32 | method ord(s) 33 | return proc("ord",0)(s[1]) 34 | end 35 | method print(root) 36 | root.print() 37 | end 38 | method node(s,r,p[]) 39 | rv := tree ! ([s,r] ||| p) 40 | return rv 41 | end 42 | method semantic(root) 43 | local out_st, System_st 44 | global_st := symtab("global") 45 | System_st := symtab("class") 46 | out_st := symtab("class") 47 | out_st.insert("println", false, , 48 | methodtype([classtype("String")], typeinfo("void"))) 49 | System_st.insert("out", false, out_st, classtype("PrintStream",out_st)) 50 | global_st.insert("System", false, System_st, classtype("System",System_st)) 51 | if \verbose then write("making symbol tables") 52 | root.mkSymTables(global_st) 53 | root.populateSymTables() 54 | if \verbose then write("checking symbol tables") 55 | root.checkSymTables() 56 | root.mkcls() 57 | # global_st.print() 58 | root.checktype() 59 | end 60 | method semerror(s) 61 | stop("semantic error: ", s) 62 | end 63 | method calctype(t) 64 | t.kids[1].calctype() 65 | t.kids[2].assigntype(t.kids[1].typ) 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /ch8/j0.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | import java.io.FileReader; 3 | public class j0 { 4 | public static Yylex yylexer; 5 | public static ch8.parser par; 6 | public static ch8.symtab global_st; 7 | public static void main(String argv[]) throws Exception { 8 | init(argv[0]); 9 | par = new ch8.parser(); 10 | // par.yydebug=true; 11 | yylineno = 1; 12 | int i = par.yyparse(); 13 | if (i == 0) 14 | System.out.println("no errors"); 15 | } 16 | public static int yylineno; 17 | public static String yyfilename; 18 | // public static parserVal yylval; 19 | public static void init(String s) throws Exception { 20 | yyfilename = s; 21 | yylexer = new Yylex(new FileReader(s)); 22 | } 23 | public static int YYEOF() { return Yylex.YYEOF; } 24 | public static int yylex() { 25 | int rv = 0; 26 | try { 27 | rv = yylexer.yylex(); 28 | } catch(java.io.IOException ioException) { 29 | rv = -1; 30 | } 31 | return rv; 32 | } 33 | public static String yytext() { 34 | return yylexer.yytext(); 35 | } 36 | public static void lexErr(String s) { 37 | System.err.println(s); 38 | System.exit(1); 39 | } 40 | public static int scan(int cat) { 41 | ch8.j0.par.yylval = 42 | new parserVal(new tree("token",cat, 43 | new token(cat, yytext(), yylineno))); 44 | return cat; 45 | } 46 | public static void newline() { 47 | yylineno++; 48 | } 49 | public static void whitespace() { 50 | } 51 | public static void comment() { 52 | } 53 | public static short ord(String s) { return (short)(s.charAt(0)); } 54 | public static void print(parserVal root) { 55 | ((tree)root.obj).print_graph(yyfilename + ".dot"); 56 | } 57 | public static tree unwrap(Object obj) { 58 | if (obj instanceof token) 59 | return new tree("token",0,(token)obj); 60 | else return (tree)obj; 61 | } 62 | public static parserVal node(String s,int r,parserVal...p) { 63 | tree[] t = new tree[p.length]; 64 | for(int i = 0; i < t.length; i++) 65 | t[i] = (tree)(p[i].obj); 66 | return new parserVal((Object)new tree(s,r,t)); 67 | } 68 | public static void semantic(parserVal r) { 69 | tree root = (tree)(r.obj); 70 | ch8.symtab out_st, System_st; 71 | global_st = new ch8.symtab("global"); 72 | System_st = new ch8.symtab("class"); 73 | out_st = new ch8.symtab("class"); 74 | out_st.insert("println", false, null, 75 | new methodtype(new typeinfo[]{new classtype("String")}, 76 | new typeinfo("void"))); 77 | System_st.insert("out", false, out_st, 78 | new classtype("PrintStream",out_st)); 79 | global_st.insert("System", false, System_st, 80 | new classtype("System",System_st)); 81 | root.mkSymTables(global_st); 82 | root.populateSymTables(); 83 | root.checkSymTables(); 84 | root.mkcls(); 85 | // global_st.print(); 86 | root.checktype(false); 87 | } 88 | public static void semerror(String s) { 89 | System.out.println("semantic error: " + s); 90 | System.exit(1); 91 | } 92 | public static void calctype(parserVal pv){ 93 | tree t = (tree)pv.obj; 94 | t.kids[0].calctype(); 95 | t.kids[1].assigntype(t.kids[0].typ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ch8/javalex.l: -------------------------------------------------------------------------------- 1 | package ch8; 2 | %% 3 | %int 4 | id=([a-zA-Z_][a-zA-Z0-9_]*) 5 | %% 6 | "/*"([^*]|"*"+[^/*])*"*"+"/" { j0.comment(); } 7 | "//".*\r?\n { j0.comment(); } 8 | [ \t\r\f]+ { j0.whitespace(); } 9 | \n { j0.newline(); } 10 | "break" { return j0.scan(parser.BREAK); } 11 | "double" { return j0.scan(parser.DOUBLE); } 12 | "else" { return j0.scan(parser.ELSE); } 13 | "false" { return j0.scan(parser.BOOLLIT); } 14 | "for" { return j0.scan(parser.FOR); } 15 | "if" { return j0.scan(parser.IF); } 16 | "int" { return j0.scan(parser.INT); } 17 | "new" { return j0.scan(parser.NEW); } 18 | "null" { return j0.scan(parser.NULLVAL); } 19 | "public" { return j0.scan(parser.PUBLIC); } 20 | "return" { return j0.scan(parser.RETURN); } 21 | "static" { return j0.scan(parser.STATIC); } 22 | "string" { return j0.scan(parser.STRING); } 23 | "true" { return j0.scan(parser.BOOLLIT); } 24 | "boolean" { return j0.scan(parser.BOOLEAN); } 25 | "void" { return j0.scan(parser.VOID); } 26 | "while" { return j0.scan(parser.WHILE); } 27 | "class" { return j0.scan(parser.CLASS); } 28 | "(" { return j0.scan(j0.ord("("));} 29 | ")" { return j0.scan(j0.ord(")"));} 30 | "[" { return j0.scan(j0.ord("["));} 31 | "]" { return j0.scan(j0.ord("]"));} 32 | "{" { return j0.scan(j0.ord("{"));} 33 | "}" { return j0.scan(j0.ord("}"));} 34 | ";" { return j0.scan(j0.ord(";"));} 35 | ":" { return j0.scan(j0.ord(":"));} 36 | "!" { return j0.scan(j0.ord("!"));} 37 | "*" { return j0.scan(j0.ord("*"));} 38 | "/" { return j0.scan(j0.ord("/"));} 39 | "%" { return j0.scan(j0.ord("%"));} 40 | "+" { return j0.scan(j0.ord("+"));} 41 | "-" { return j0.scan(j0.ord("-"));} 42 | "<" { return j0.scan(j0.ord("<"));} 43 | "<=" { return j0.scan(parser.LESSTHANOREQUAL);} 44 | ">" { return j0.scan(j0.ord(">"));} 45 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 46 | "==" { return j0.scan(parser.ISEQUALTO);} 47 | "!=" { return j0.scan(parser.NOTEQUALTO);} 48 | "&&" { return j0.scan(parser.LOGICALAND);} 49 | "||" { return j0.scan(parser.LOGICALOR);} 50 | "=" { return j0.scan(j0.ord("=")); } 51 | "+=" { return j0.scan(parser.INCREMENT); } 52 | "-=" { return j0.scan(parser.DECREMENT); } 53 | "," { return j0.scan(j0.ord(",")); } 54 | "." { return j0.scan(j0.ord(".")); } 55 | {id} { return j0.scan(parser.IDENTIFIER); } 56 | [0-9]+ { return j0.scan(parser.INTLIT); } 57 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 58 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 59 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 60 | . { j0.lexErr("unrecognized character"); } 61 | -------------------------------------------------------------------------------- /ch8/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u typeinfo.u 6 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) 7 | unicon: j0 8 | %.u : %.icn 9 | unicon -c $< 10 | j0: $(U) 11 | unicon $(U) 12 | javalex.icn: javalex.l 13 | uflex javalex.l 14 | j0gram.icn j0gram_tab.icn: j0gram.y 15 | iyacc -dd j0gram.y 16 | 17 | # A typical run might use 18 | # set CLASSPATH=".;c:\users\username\byopl" 19 | # in order to run from c:\users\username\byopl\ch8 20 | LYSRC=Yylex.java parser.java parserVal.java 21 | TPJ=typeinfo.java arraytype.java classtype.java methodtype.java parameter.java 22 | STJ=symtab.java symtab_entry.java $(TPJ) 23 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) 24 | BYJOPTS= -Jclass=parser -Jpackage=ch8 25 | BYJIMPS= -Jyylex=ch8.j0.yylex -Jyyerror=ch8.yyerror.yyerror 26 | java: j0.class 27 | 28 | j: java 29 | java ch8.j0 hello.java 30 | dot -Tpng hello.java.dot >hello.png 31 | 32 | j0.class: $(JSRC) 33 | javac $(JSRC) 34 | parser.java parserVal.java: j0gram.y 35 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 36 | Yylex.java: javalex.l 37 | jflex javalex.l 38 | 39 | -------------------------------------------------------------------------------- /ch8/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | public class methodtype extends typeinfo { 3 | typeinfo [] parameters; 4 | typeinfo return_type; 5 | public String str() { 6 | String s; 7 | s = "method " + ((return_type!=null)?return_type.str():"undef") + "("; 8 | for(typeinfo p : parameters) 9 | s = s + p.str() + ","; 10 | s = s.substring(0,s.length()-2) + ")"; 11 | return s; 12 | } 13 | methodtype(typeinfo [] p, typeinfo rt){ 14 | parameters = p; 15 | if (rt !=null) return_type = rt; 16 | else return_type = new typeinfo("void"); 17 | basetype="method"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch8/parameter.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch8/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch8/serial.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch8/symtab.icn: -------------------------------------------------------------------------------- 1 | class symtab(scope, parent, t) 2 | method lookup(s) 3 | return if rv := \ (t[s]) then { 4 | rv } 5 | else { 6 | (\parent).lookup(s) 7 | } 8 | end 9 | method insert(s, isConst, sub, typ) 10 | if \ (t[s]) then j0.semerror("redeclaration of " || s) 11 | else { (\sub).parent := self 12 | t[s] := symtab_entry(s, self, sub, isConst, typ) } 13 | end 14 | method print(level:0) 15 | writes(repl(" ",level)) 16 | write(scope, " - ", *t, " symbols") 17 | every (!t).print(level+1); 18 | end 19 | 20 | initially 21 | t := table() 22 | end 23 | -------------------------------------------------------------------------------- /ch8/symtab.java: -------------------------------------------------------------------------------- 1 | package ch8; 2 | import java.util.HashMap; 3 | public class symtab { 4 | String scope; 5 | symtab parent; 6 | HashMap t; 7 | symtab(String sc) { 8 | scope = sc; 9 | t = new HashMap(); 10 | } 11 | symtab(String sc, symtab p) { 12 | scope = sc; parent = p; 13 | t = new HashMap(); 14 | } 15 | symtab_entry lookup(String s) { 16 | symtab_entry rv; 17 | rv = t.get(s); 18 | if (rv != null) { 19 | return rv; 20 | } 21 | if (parent != null) return parent.lookup(s); 22 | return null; 23 | } 24 | void insert(String s, Boolean iC, symtab sub, typeinfo typ) { 25 | if (t.containsKey(s)) { 26 | j0.semerror("redeclaration of " + s); 27 | } else { 28 | if (sub != null) 29 | sub.parent = this; 30 | t.put(s, new symtab_entry(s, this, iC, sub, typ)); 31 | } 32 | } 33 | void insert(String s, Boolean iC) { 34 | if (t.containsKey(s)) { 35 | j0.semerror("redeclaration of " + s); 36 | } else { 37 | t.put(s, new symtab_entry(s, this, iC)); 38 | } 39 | } 40 | void print() { print(0); } 41 | void print(int level) { 42 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /ch9/address.icn: -------------------------------------------------------------------------------- 1 | class address(region, offset) 2 | method regaddr() 3 | return if region == "method" then "loc" else region 4 | end 5 | method str() 6 | case region of { 7 | "lab": return "L"||offset 8 | "loc"|"imm"|"method"|"global"|"class"|"strings": 9 | return regaddr() || ":" || offset 10 | } 11 | return region 12 | end 13 | method print() 14 | writes(str()) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /ch9/address.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | public class address { 3 | public String region; 4 | public int offset; 5 | public String regaddr() { return region.equals("method")?"loc":region; } 6 | public String str() { 7 | switch (region) { 8 | case "lab": return "L" + offset; 9 | case "loc": case "imm": case "method": 10 | case "global": case "class": case "strings": 11 | return regaddr() + ":" + offset; 12 | } 13 | return region; 14 | } 15 | public void print() { System.out.print(str()); } 16 | address(String s, int o) { region = s; offset = o; } 17 | } 18 | -------------------------------------------------------------------------------- /ch9/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | public class arraytype extends typeinfo { 3 | typeinfo element_type; 4 | public String str() { 5 | return "array of " + (element_type!=null?element_type.str():"undef"); 6 | } 7 | public arraytype(typeinfo t) { 8 | basetype = "array"; element_type = t; } 9 | } 10 | -------------------------------------------------------------------------------- /ch9/arrtst.java: -------------------------------------------------------------------------------- 1 | public class arrtst { 2 | public static void main(String argv[]) { 3 | int x[]; 4 | x = new int[3]; 5 | x[1] = 0; 6 | x[0] = x[1]; 7 | x[2] = argv[1]; 8 | System.out.println("hello, world"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch9/classtype.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | public class classtype extends typeinfo { 3 | String name; 4 | symtab st; 5 | parameter [] methods; 6 | parameter [] fields; 7 | typeinfo [] constrs; 8 | public String str() { 9 | return name; 10 | } 11 | public classtype(String s) { name = s; basetype="class";} 12 | public classtype(String s, symtab stab) { name = s; st = stab; basetype="class";} 13 | public classtype(String s, symtab stab, 14 | parameter []ms, parameter[]fs, typeinfo[]cs) { 15 | name = s; st = stab; methods=ms; fields=fs; constrs=cs; basetype="class";} 16 | } 17 | -------------------------------------------------------------------------------- /ch9/clstest.java: -------------------------------------------------------------------------------- 1 | public class clstest { 2 | public static void main(String argv[]) { 3 | clstest c; 4 | c = new clstest(); 5 | System.out.println("hello, jzero!"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch9/funtest.java: -------------------------------------------------------------------------------- 1 | public class funtest { 2 | public static int foo(int x, int y, String z) { 3 | return 0; 4 | } 5 | public static void main(String argv[]) { 6 | int x; 7 | x = foo(0,1,"howdy"); 8 | x = x + 1; 9 | System.out.println("hello, jzero!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch9/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | int x; 4 | x = argv.length; 5 | x = x + 2; 6 | while (x > 3) { 7 | System.out.println("hello, jzero!"); 8 | x = x - 1; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch9/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch9/j0.icn: -------------------------------------------------------------------------------- 1 | global yylineno, yycolno, yylval, parser, global_st, stringtab 2 | procedure main(argv) 3 | j0 := j0() 4 | serial := serial() 5 | parser := Parser() 6 | yyin := open(argv[1]) | stop("usage: j0 filename") 7 | yylineno := yycolno := 1 8 | if yyparse() = 0 then 9 | write("no errors") 10 | end 11 | class j0() 12 | method lexErr(s) 13 | stop(s, ": ", yytext) 14 | end 15 | method scan(cat) 16 | yylval := tree("token", cat, token(cat, yytext, yylineno, yycolno)) 17 | yycolno +:= *yytext 18 | return cat 19 | end 20 | method whitespace() 21 | yycolno +:= *yytext 22 | end 23 | method newline() 24 | yylineno +:= 1; yycolno := 1 25 | end 26 | method comment() 27 | yytext ? { 28 | while tab(find("\n")+1) do newline() 29 | yycolno +:= *tab(0) 30 | } 31 | end 32 | method ord(s) 33 | return proc("ord",0)(s[1]) 34 | end 35 | method print(root) 36 | root.print() 37 | end 38 | method node(s,r,p[]) 39 | rv := tree ! ([s,r] ||| p) 40 | return rv 41 | end 42 | method semantic(root) 43 | local out_st, System_st 44 | global_st := symtab("global") 45 | stringtab := symtab("strings") 46 | System_st := symtab("class") 47 | out_st := symtab("class") 48 | out_st.insert("println", false, , 49 | methodtype([classtype("String")], typeinfo("void"))) 50 | System_st.insert("out", false, out_st, classtype("PrintStream",out_st)) 51 | global_st.insert("System", false, System_st, classtype("System",System_st)) 52 | if \verbose then write("making symbol tables") 53 | root.mkSymTables(global_st) 54 | root.populateSymTables() 55 | if \verbose then write("checking symbol tables") 56 | root.checkSymTables() 57 | root.mkcls() 58 | # global_st.print() 59 | root.checktype() 60 | end 61 | method semErr(s) 62 | stop("semantic error: ", s) 63 | end 64 | method calctype(t) 65 | t.kids[1].calctype() 66 | t.kids[2].assigntype(t.kids[1].typ) 67 | end 68 | method gencode(root) 69 | root.genfirst() 70 | root.genfollow() 71 | root.gentargets() 72 | root.gencode() 73 | every (! (\root.icode)).print() 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /ch9/j0gram_tab.icn: -------------------------------------------------------------------------------- 1 | class Parser(BREAK, DOUBLE, ELSE, FOR, IF, INT, RETURN, VOID, WHILE, IDENTIFIER, CLASSNAME, CLASS, STRING, BOOL, INTLIT, DOUBLELIT, STRINGLIT, BOOLLIT, NULLVAL, LESSTHANOREQUAL, GREATERTHANOREQUAL, ISEQUALTO, NOTEQUALTO, LOGICALAND, LOGICALOR, INCREMENT, DECREMENT, PUBLIC, STATIC, NEW, BOOLEAN) 2 | initially 3 | BREAK := 257 4 | DOUBLE := 258 5 | ELSE := 259 6 | FOR := 260 7 | IF := 261 8 | INT := 262 9 | RETURN := 263 10 | VOID := 264 11 | WHILE := 265 12 | IDENTIFIER := 266 13 | CLASSNAME := 267 14 | CLASS := 268 15 | STRING := 269 16 | BOOL := 270 17 | INTLIT := 271 18 | DOUBLELIT := 272 19 | STRINGLIT := 273 20 | BOOLLIT := 274 21 | NULLVAL := 275 22 | LESSTHANOREQUAL := 276 23 | GREATERTHANOREQUAL := 277 24 | ISEQUALTO := 278 25 | NOTEQUALTO := 279 26 | LOGICALAND := 280 27 | LOGICALOR := 281 28 | INCREMENT := 282 29 | DECREMENT := 283 30 | PUBLIC := 284 31 | STATIC := 285 32 | NEW := 286 33 | BOOLEAN := 287 34 | end 35 | -------------------------------------------------------------------------------- /ch9/javalex.l: -------------------------------------------------------------------------------- 1 | package ch9; 2 | %% 3 | %int 4 | id=([a-zA-Z_][a-zA-Z0-9_]*) 5 | %% 6 | "/*"([^*]|"*"+[^/*])*"*"+"/" { j0.comment(); } 7 | "//".*\r?\n { j0.comment(); } 8 | [ \t\r\f]+ { j0.whitespace(); } 9 | \n { j0.newline(); } 10 | "break" { return j0.scan(parser.BREAK); } 11 | "double" { return j0.scan(parser.DOUBLE); } 12 | "else" { return j0.scan(parser.ELSE); } 13 | "false" { return j0.scan(parser.BOOLLIT); } 14 | "for" { return j0.scan(parser.FOR); } 15 | "if" { return j0.scan(parser.IF); } 16 | "int" { return j0.scan(parser.INT); } 17 | "new" { return j0.scan(parser.NEW); } 18 | "null" { return j0.scan(parser.NULLVAL); } 19 | "public" { return j0.scan(parser.PUBLIC); } 20 | "return" { return j0.scan(parser.RETURN); } 21 | "static" { return j0.scan(parser.STATIC); } 22 | "string" { return j0.scan(parser.STRING); } 23 | "true" { return j0.scan(parser.BOOLLIT); } 24 | "boolean" { return j0.scan(parser.BOOLEAN); } 25 | "void" { return j0.scan(parser.VOID); } 26 | "while" { return j0.scan(parser.WHILE); } 27 | "class" { return j0.scan(parser.CLASS); } 28 | "(" { return j0.scan(j0.ord("("));} 29 | ")" { return j0.scan(j0.ord(")"));} 30 | "[" { return j0.scan(j0.ord("["));} 31 | "]" { return j0.scan(j0.ord("]"));} 32 | "{" { return j0.scan(j0.ord("{"));} 33 | "}" { return j0.scan(j0.ord("}"));} 34 | ";" { return j0.scan(j0.ord(";"));} 35 | ":" { return j0.scan(j0.ord(":"));} 36 | "!" { return j0.scan(j0.ord("!"));} 37 | "*" { return j0.scan(j0.ord("*"));} 38 | "/" { return j0.scan(j0.ord("/"));} 39 | "%" { return j0.scan(j0.ord("%"));} 40 | "+" { return j0.scan(j0.ord("+"));} 41 | "-" { return j0.scan(j0.ord("-"));} 42 | "<" { return j0.scan(j0.ord("<"));} 43 | "<=" { return j0.scan(parser.LESSTHANOREQUAL);} 44 | ">" { return j0.scan(j0.ord(">"));} 45 | ">=" { return j0.scan(parser.GREATERTHANOREQUAL);} 46 | "==" { return j0.scan(parser.ISEQUALTO);} 47 | "!=" { return j0.scan(parser.NOTEQUALTO);} 48 | "&&" { return j0.scan(parser.LOGICALAND);} 49 | "||" { return j0.scan(parser.LOGICALOR);} 50 | "=" { return j0.scan(j0.ord("=")); } 51 | "+=" { return j0.scan(parser.INCREMENT); } 52 | "-=" { return j0.scan(parser.DECREMENT); } 53 | "," { return j0.scan(j0.ord(",")); } 54 | "." { return j0.scan(j0.ord(".")); } 55 | {id} { return j0.scan(parser.IDENTIFIER); } 56 | [0-9]+ { return j0.scan(parser.INTLIT); } 57 | [0-9]*"."[0-9]*([eE][+-]?[0-9]+)? { return j0.scan(parser.DOUBLELIT); } 58 | ([0-9]+)([eE][+-]?([0-9]+)) { return j0.scan(parser.DOUBLELIT); } 59 | \"([^\"]|(\\.))*\" { return j0.scan(parser.STRINGLIT); } 60 | . { j0.lexErr("unrecognized character"); } 61 | -------------------------------------------------------------------------------- /ch9/makefile: -------------------------------------------------------------------------------- 1 | 2 | all: java unicon 3 | 4 | LYU=javalex.u j0gram.u j0gram_tab.u 5 | STU=symtab.u symtab_entry.u typeinfo.u 6 | CGU=tac.u address.u 7 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) $(CGU) 8 | unicon: j0 9 | %.u : %.icn 10 | unicon -c $< 11 | j0: $(U) 12 | unicon $(U) 13 | javalex.icn: javalex.l 14 | uflex javalex.l 15 | j0gram.icn j0gram_tab.icn: j0gram.y 16 | iyacc -dd j0gram.y 17 | 18 | # Windows: a typical run might use 19 | # set CLASSPATH=".;c:\users\username\byopl" 20 | # in order to run from c:\users\username\byopl\ch9 21 | LYSRC=Yylex.java parser.java parserVal.java 22 | TPJ=typeinfo.java arraytype.java classtype.java methodtype.java parameter.java 23 | STJ=symtab.java symtab_entry.java $(TPJ) 24 | CGJ=tac.java address.java 25 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) $(CGJ) 26 | BYJOPTS= -Jclass=parser -Jpackage=ch9 27 | BYJIMPS= -Jyylex=ch9.j0.yylex -Jyyerror=ch9.yyerror.yyerror 28 | java: j0.class 29 | 30 | j: java 31 | java ch9.j0 hello.java 32 | dot -Tpng hello.java.dot >hello.png 33 | 34 | j0.class: $(JSRC) 35 | javac $(JSRC) 36 | parser.java parserVal.java: j0gram.y 37 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 38 | Yylex.java: javalex.l 39 | jflex javalex.l 40 | 41 | -------------------------------------------------------------------------------- /ch9/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | public class methodtype extends typeinfo { 3 | typeinfo [] parameters; 4 | typeinfo return_type; 5 | public String str() { 6 | String s; 7 | s = "method " + ((return_type!=null)?return_type.str():"undef") + "("; 8 | for(typeinfo p : parameters) 9 | s = s + p.str() + ","; 10 | s = s.substring(0,s.length()-2) + ")"; 11 | return s; 12 | } 13 | methodtype(typeinfo [] p, typeinfo rt){ 14 | parameters = p; 15 | if (rt !=null) return_type = rt; 16 | else return_type = new typeinfo("void"); 17 | basetype="method"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch9/parameter.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch9/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch9; 6 | 7 | /** 8 | * BYACC/J Semantic Value for parser: parser 9 | * This class provides some of the functionality 10 | * of the yacc/C 'union' directive 11 | */ 12 | public class parserVal 13 | { 14 | /** 15 | * integer value of this 'union' 16 | */ 17 | public int ival; 18 | 19 | /** 20 | * double value of this 'union' 21 | */ 22 | public double dval; 23 | 24 | /** 25 | * string value of this 'union' 26 | */ 27 | public String sval; 28 | 29 | /** 30 | * object value of this 'union' 31 | */ 32 | public Object obj; 33 | 34 | //############################################# 35 | //## C O N S T R U C T O R S 36 | //############################################# 37 | /** 38 | * Initialize me without a value 39 | */ 40 | public parserVal() 41 | { 42 | } 43 | /** 44 | * Initialize me as an int 45 | */ 46 | public parserVal(int val) 47 | { 48 | ival=val; 49 | } 50 | 51 | /** 52 | * Initialize me as a double 53 | */ 54 | public parserVal(double val) 55 | { 56 | dval=val; 57 | } 58 | 59 | /** 60 | * Initialize me as a string 61 | */ 62 | public parserVal(String val) 63 | { 64 | sval=val; 65 | } 66 | 67 | /** 68 | * Initialize me as an Object 69 | */ 70 | public parserVal(Object val) 71 | { 72 | obj=val; 73 | } 74 | }//end class 75 | 76 | //############################################# 77 | //## E N D O F F I L E 78 | //############################################# 79 | -------------------------------------------------------------------------------- /ch9/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch9/serial.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch9/symtab.icn: -------------------------------------------------------------------------------- 1 | class symtab(scope, parent, t, count) 2 | method lookup(s) 3 | return if rv := \ (t[s]) then { 4 | rv } 5 | else { 6 | (\parent).lookup(s) 7 | } 8 | end 9 | method insert(s, isConst, sub, typ) 10 | if \ (t[s]) then { 11 | if scope == "strings" then { 12 | # write("eureka, a duplicate string constant") 13 | } 14 | else 15 | j0.semErr("redeclaration of " || s) 16 | } 17 | else { 18 | (\sub).parent := self 19 | t[s] := symtab_entry(s, self, sub, isConst, typ, 20 | address(scope,count)) 21 | count +:= 8 22 | } 23 | end 24 | method genlocal() 25 | local s := "__local$" || count 26 | insert(s, false, , typeinfo("int")) 27 | return t[s].addr 28 | end 29 | method print(level:0) 30 | writes(repl(" ",level)) 31 | write(scope, " - ", *t, " symbols") 32 | every (!t).print(level+1); 33 | end 34 | 35 | initially 36 | t := table() 37 | count := 0 38 | end 39 | -------------------------------------------------------------------------------- /ch9/symtab.java: -------------------------------------------------------------------------------- 1 | package ch9; 2 | import java.util.HashMap; 3 | public class symtab { 4 | String scope; 5 | symtab parent; 6 | HashMap t; 7 | int count; 8 | symtab(String sc) { 9 | scope = sc; 10 | t = new HashMap(); 11 | } 12 | symtab(String sc, symtab p) { 13 | scope = sc; parent = p; 14 | t = new HashMap(); 15 | } 16 | symtab_entry lookup(String s) { 17 | symtab_entry rv; 18 | rv = t.get(s); 19 | if (rv != null) { 20 | return rv; 21 | } 22 | if (parent != null) return parent.lookup(s); 23 | return null; 24 | } 25 | void insert(String s, Boolean iC, symtab sub, typeinfo typ) { 26 | if (t.containsKey(s)) { 27 | j0.semErr("redeclaration of " + s); 28 | } else { 29 | if (sub != null) 30 | sub.parent = this; 31 | t.put(s, new symtab_entry(s, this, iC, sub, typ, 32 | new address(scope,count))); 33 | count += 8; 34 | } 35 | } 36 | address genlocal() { 37 | String s = "__local$" + count; 38 | insert(s, false, null, new typeinfo("int")); 39 | return t.get(s).addr; 40 | } 41 | void insert(String s, Boolean iC) { 42 | if (t.containsKey(s)) { 43 | j0.semErr("redeclaration of " + s); 44 | } else { 45 | t.put(s, new symtab_entry(s, this, iC)); 46 | } 47 | } 48 | void print() { print(0); } 49 | void print(int level) { 50 | for(int i=0; i 10) { 31 | System.err.println("too many errors, aborting"); 32 | System.exit(__merr_errors); 33 | } 34 | if (j0.yyfilename != null) { 35 | System.err.print(j0.yyfilename+":"); 36 | } 37 | int state = j0.par.yystate; 38 | if (state > yymaxstate) { 39 | int j; 40 | errortable et[] = new errortable[state+1]; 41 | for (j = 0; j < yymaxstate; j++) 42 | et[j] = errtab[j]; 43 | // for (; j <= state; j++) { 44 | // et[j] = new errortable(1, "syntax error"); 45 | // } 46 | errtab = et; 47 | yymaxstate = state; 48 | } 49 | 50 | if ((s.equals("syntax error") || s.equals("parse error")) && 51 | (state >= 0) && (state <= yymaxstate)) { 52 | if (errtab[state].i == 1) { 53 | s = errtab[state].msg; 54 | } 55 | else { 56 | int i; 57 | for(i=1;i<=errtab[state].i;i++) 58 | if (j0.par.yychar == errtab[state].p[i].i) { 59 | s=errtab[state].p[i].msg; break; 60 | } 61 | if (i>errtab[state].i && errtab[state].i > 0) 62 | s = errtab[state].p[0].msg; 63 | } 64 | } 65 | if (s.equals("syntax error") || s.equals("parse error")) { 66 | s = s+" ("+state+";"+j0.par.yychar+")"; 67 | } 68 | System.err.println(j0.yylineno+": # \\\"" + j0.yytext() + "\\\": "+s); 69 | } 70 | } 71 | 72 | --------------------------------------------------------------------------------