├── LICENSE ├── README.md ├── ch11 ├── Op.icn ├── Op.java ├── address.icn ├── address.java ├── arraytype.java ├── arrtst.java ├── byc.icn ├── byc.java ├── classtype.java ├── clstest.java ├── foo.icn ├── funtest.java ├── hello.icn ├── hello.j0 ├── hello.java ├── hello.png ├── hello1a.icn ├── hello1a.java ├── hello1a_helper.icn ├── hello1b.icn ├── hello1b.java ├── hello1b_helper.icn ├── hello1c.icn ├── hello1c.java ├── hello1c_helper.icn ├── hello1d.icn ├── hello1d.java ├── hello1d_helper.icn ├── hello2.icn ├── hello2.java ├── hello2_helper.icn ├── hello_helper.icn ├── hello_stub.icn ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.y ├── j0gram_tab.icn ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.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 ├── ch12 ├── Op.icn ├── Op.java ├── hello.j0 ├── hello.java ├── j0machine.icn ├── j0machine.java ├── j0x.icn ├── j0x.java ├── makefile └── writehello.icn ├── ch13 ├── j0machine.icn ├── j0x.icn ├── tree.icn └── tree.java ├── ch3 ├── dorrie.in ├── dorrie.std ├── dorrie2.in ├── dorrie2.std ├── hello.java ├── hello.std ├── j0.icn ├── j0.java ├── j0go.icn ├── j0go.java ├── javalex.l ├── makefile ├── makefile.win ├── nnws-tok.l ├── nnws.l ├── parser.java ├── simple.icn ├── simple.java ├── simple2.icn ├── simple2.java └── token.java ├── ch4 ├── dorrie.out ├── dorrie3.in ├── dorrie3.std ├── hello.java ├── hello.out ├── hello.std ├── helloerror.java ├── j0.icn ├── j0.java ├── j0go.icn ├── j0go.java ├── j0gram.y ├── j0gram_tab.icn ├── javalex.l ├── jzero.java ├── lexer.java ├── makefile ├── makefile.win ├── nameseq.y ├── nnws.l ├── ns.y ├── ns_tab.icn ├── parserTokens.java ├── parserVal.java ├── token.java ├── trivial.icn ├── trivial.java ├── yyerror.icn └── yyerror.java ├── ch5 ├── hello.java ├── hello.out ├── hello.std ├── helloerror.java ├── hellostd.png ├── j0.icn ├── j0.java ├── j0gram.y ├── j0gram_tab.icn ├── javalex.l ├── makefile ├── makefile.win ├── 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 ├── makefile.win ├── 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 ├── arraytype.java ├── classtype.java ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.y ├── j0gram_tab.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 ├── j0gram_tab.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 └── ch9 ├── address.icn ├── address.java ├── arraytype.java ├── arrtst.java ├── classtype.java ├── clstest.java ├── funtest.java ├── hello.java ├── helloerror.java ├── j0.icn ├── j0.java ├── j0gram.y ├── j0gram_tab.icn ├── javalex.l ├── makefile ├── methodtype.java ├── parameter.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) 2023 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, 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 | -------------------------------------------------------------------------------- /ch11/Op.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/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 | end 13 | -------------------------------------------------------------------------------- /ch11/address.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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() { if (region.equals("lab")) return "L"+offset; 7 | return regaddr() + ":" + offset; } 8 | public void print() { System.out.print(str()); } 9 | address(String s, int o) { region = s; offset = o; } 10 | } 11 | -------------------------------------------------------------------------------- /ch11/arraytype.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/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 | -------------------------------------------------------------------------------- /ch11/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 | # return "unknownaddr" 33 | end 34 | 35 | method printb(f:&output) 36 | writes(f, char(op), char(\opreg|0)) 37 | x := (\opnd | 0) 38 | every !6 do { 39 | writes(f, char(iand(x, 255))) 40 | x := ishift(x, -8) 41 | } 42 | end 43 | method addr(a) 44 | if /a then opreg := Op.R_NONE 45 | else if type(a) == "integer" then { 46 | opreg := Op.R_IMM; opnd := a 47 | } 48 | else if type(a) == "string" then { 49 | if not (sa := stringtab.lookup(a)) then write("don't know ", image(a)) 50 | # string region addresses are just pointers offset 24 from start 51 | opreg := Op.R_IMM; opnd := sa.addr.offset + 24 52 | } 53 | else case a.region of { 54 | "method": { opreg := Op.R_STACK; opnd := a.offset } 55 | "global": { opreg := Op.R_ABS; opnd := a.offset + stringtab.count } 56 | "const": { opreg := Op.R_ABS; opnd := a.offset } 57 | "lab": { opreg := Op.R_ABS; opnd := a.offset } 58 | "obj": { opreg := Op.R_HEAP; opnd := a.offset } 59 | "imm": { opreg := Op.R_IMM; opnd := a.offset } 60 | "strings": { opreg := Op.R_IMM; opnd := a.offset + 24 } 61 | default: { 62 | write("system error. region ", image(a.region), 63 | " offset ", image(a.offset)) 64 | runerr(103, a.region) 65 | } 66 | } 67 | end 68 | initially(o, a) 69 | op := o; addr(a); # addr(\a) 70 | if type(nameof()) ~== "string" then { 71 | write(&errout, "bad op ", image(op)) 72 | runerr(103, op) 73 | } 74 | end 75 | -------------------------------------------------------------------------------- /ch11/byc.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/classtype.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/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 | -------------------------------------------------------------------------------- /ch11/foo.icn: -------------------------------------------------------------------------------- 1 | class foo(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch11/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 | -------------------------------------------------------------------------------- /ch11/hello.icn: -------------------------------------------------------------------------------- 1 | package hello 2 | procedure main(argv) 3 | write( 4 | "hello, jzero!" 5 | ) 6 | end 7 | class hello() 8 | end 9 | -------------------------------------------------------------------------------- /ch11/hello.j0: -------------------------------------------------------------------------------- 1 | Jzero!!1.0hello, jzero! X   ÿÿÿÿÿÿ   2 |    -------------------------------------------------------------------------------- /ch11/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch11/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Build-your-own-Programming-Language-Second-Edition/36b60db1a08b39d7695b20eca9aece26babf1c00/ch11/hello.png -------------------------------------------------------------------------------- /ch11/hello1a.icn: -------------------------------------------------------------------------------- 1 | package hello1a 2 | procedure main(argv [ ]) 3 | if 1===2 then { 4 | write("hello, jzero!") 5 | } 6 | end 7 | class hello1a() 8 | end 9 | -------------------------------------------------------------------------------- /ch11/hello1a.java: -------------------------------------------------------------------------------- 1 | public class hello1a { 2 | public static void main(String argv[]) { 3 | if(1==2) { 4 | System.out.println("hello, jzero!"); 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch11/hello1a_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello1a__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello1b.icn: -------------------------------------------------------------------------------- 1 | package hello1b 2 | procedure main(argv [ ]) 3 | if 1===2 then 4 | { 5 | write("hello, jzero!") 6 | } 7 | else 8 | { 9 | write("goodbye, jzero!") 10 | } 11 | end 12 | class hello1b() 13 | end 14 | -------------------------------------------------------------------------------- /ch11/hello1b.java: -------------------------------------------------------------------------------- 1 | public class hello1b { 2 | public static void main(String argv[]) { 3 | if(1==2) { 4 | System.out.println("hello, jzero!"); 5 | } 6 | else { 7 | System.out.println("goodbye, jzero!"); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch11/hello1b_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello1b__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello1c.icn: -------------------------------------------------------------------------------- 1 | package hello1c 2 | procedure main(argv [ ]) 3 | local 4 | x 5 | x:=1 6 | x:=( x +1) 7 | end 8 | class hello1c() 9 | end 10 | -------------------------------------------------------------------------------- /ch11/hello1c.java: -------------------------------------------------------------------------------- 1 | public class hello1c { 2 | public static void main(String argv[]) { 3 | int x; 4 | x = 1; 5 | x = x + 1; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch11/hello1c_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello1c__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello1d.icn: -------------------------------------------------------------------------------- 1 | package hello1d 2 | procedure main(argv [ ]) 3 | local 4 | x 5 | x:=1 6 | while x < 4 do 7 | { 8 | write("up") 9 | x:=( x +1) 10 | } 11 | end 12 | class hello1d() 13 | end 14 | -------------------------------------------------------------------------------- /ch11/hello1d.java: -------------------------------------------------------------------------------- 1 | public class hello1d { 2 | public static void main(String argv[]) { 3 | int x; 4 | x = 1; 5 | while (x < 4) { 6 | System.out.println("up"); 7 | x = x + 1; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch11/hello1d_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello1d__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello2.icn: -------------------------------------------------------------------------------- 1 | package hello2 2 | procedure main(a) 3 | local 4 | x 5 | x:=*argv 6 | x:=( x +2) 7 | while x > 3 do { 8 | write("hello, jzero!") 9 | x:=( x -1) 10 | } 11 | end 12 | class hello2() 13 | end 14 | -------------------------------------------------------------------------------- /ch11/hello2.java: -------------------------------------------------------------------------------- 1 | public class hello2 { 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 | -------------------------------------------------------------------------------- /ch11/hello2_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello2__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello_helper.icn: -------------------------------------------------------------------------------- 1 | procedure main(argv) 2 | hello__main ! argv 3 | end 4 | -------------------------------------------------------------------------------- /ch11/hello_stub.icn: -------------------------------------------------------------------------------- 1 | procedure main(args) 2 | hello__main ! args 3 | end 4 | -------------------------------------------------------------------------------- /ch11/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch11/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 | -------------------------------------------------------------------------------- /ch11/javalex.l: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/makefile: -------------------------------------------------------------------------------- 1 | all: java unicon 2 | 3 | LYU=javalex.u j0gram.u j0gram_tab.u 4 | STU=symtab.u symtab_entry.u typeinfo.u 5 | CGU=tac.u address.u byc.u Op.u 6 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) $(CGU) 7 | YACC=byaccj 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 | # A typical run might use 19 | # set CLASSPATH=".;c:\users\username\byopl" 20 | # in order to run from c:\users\username\byopl\ch11_2e 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 byc.java Op.java 25 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) $(CGJ) 26 | BYJOPTS= -Jclass=parser -Jpackage=ch11_2e 27 | BYJIMPS= -Jyylex=ch11_2e.j0.yylex -Jyyerror=ch11_2e.yyerror.yyerror 28 | java: j0.class 29 | 30 | j: java 31 | java ch11_2e.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 | -------------------------------------------------------------------------------- /ch11/methodtype.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/parameter.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 2 | public class parameter { 3 | String name; 4 | typeinfo param_type; 5 | parameter(String s, typeinfo t) { name=s; param_type=t; } 6 | } 7 | -------------------------------------------------------------------------------- /ch11/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch11/serial.icn: -------------------------------------------------------------------------------- 1 | class serial(serialno) 2 | method getid() 3 | serialno +:= 1; return serialno 4 | end 5 | initially 6 | serialno := 0 7 | end 8 | -------------------------------------------------------------------------------- /ch11/serial.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 2 | class serial { 3 | static int serial; 4 | public static int getid(){ serial++; return serial; } 5 | } 6 | -------------------------------------------------------------------------------- /ch11/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 | -------------------------------------------------------------------------------- /ch11/symtab.java: -------------------------------------------------------------------------------- 1 | package ch11_2e; 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 | -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /ch12/hello.j0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Build-your-own-Programming-Language-Second-Edition/36b60db1a08b39d7695b20eca9aece26babf1c00/ch12/hello.j0 -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /ch12/j0machine.icn: -------------------------------------------------------------------------------- 1 | link signed 2 | class j0machine(code, ip, stack, data, finstr, sp, bp, hp, op, opr, opnd) 3 | # loadbytecode at present returns everything after the first two-words of header 4 | method loadbytecode(filename) 5 | sz := stat(filename).size 6 | f := open(filename) | stop("cannot open ", filename) 7 | s := reads(f, sz) | stop("cannot read from ", filename) 8 | close(f) 9 | s ? { 10 | if tab(find("Jzero!!\0001.0\0\0\0\0\0")) then { 11 | return tab(0) 12 | } 13 | else stop("file ", filename, " is not a Jzero file") 14 | } 15 | end 16 | method init(filename) 17 | ip := 0 18 | code := loadbytecode(filename) | 19 | stop("cannot open program.j0") 20 | Op() 21 | ip := 16 22 | ip := finstr := 8*getOpnd() 23 | data := Data(code[25:ip+1]) 24 | stack := list() 25 | bp := sp := 1 26 | end 27 | method fetch() 28 | op := ord(code[1+ip]) 29 | opr := ord(code[2+ip]) 30 | if opr ~= 0 then { opnd := getOpnd() } 31 | ip +:= 8 32 | end 33 | method getOpnd() 34 | return signed(reverse(code[ip+3+:6])) 35 | end 36 | method word(s) 37 | local i := 0, j 38 | every j := 8 to 1 by -1 do { 39 | b := ord(s[j]) 40 | i := ishift(i, 8) + ord(b) 41 | } 42 | return i 43 | end 44 | method interp() 45 | repeat { 46 | fetch() 47 | case (op) of { 48 | Op.HALT: { stop("Execution completed.") } 49 | Op.NOOP: { } 50 | Op.ADD: { 51 | val1 := pop(stack); val2 := pop(stack) 52 | push(stack, val1 + val2) 53 | } 54 | Op.PUSH: { 55 | (val := deref(opr, opnd)) | stop("deref failed") 56 | push(stack, val) 57 | } 58 | Op.POP: { 59 | val := pop(stack) 60 | assign(opnd, val) 61 | } 62 | Op.GOTO: { 63 | ip := opnd 64 | } 65 | Op.BIF: { 66 | if pop(stack)~=0 then 67 | ip := opnd 68 | } 69 | Op.CALL: { 70 | f := stack[1+opnd] 71 | if f >= 0 then { 72 | push( stack, ip) # save old ip 73 | push( stack, bp) # save old ip 74 | bp := *stack # set new bp 75 | ip := f # set new ip 76 | } 77 | else if f = -1 then do_println() 78 | else stop("no CALL defined for ", image(f)) 79 | } 80 | Op.RETURN: { 81 | while *stack > bp do pop(stack) 82 | bp := pop(stack) 83 | ip := pop( stack ) 84 | } 85 | 86 | Op.LT: { } 87 | Op.LE: { } 88 | default: { stop("Illegal opcode ", op) } 89 | } 90 | } 91 | end 92 | method do_println() 93 | x := stack[1] 94 | y := c_string(code[1+x:0]) 95 | write(y) 96 | end 97 | method c_string(s) 98 | if i := find("\0", s) then return s[1:i] 99 | else stop("no C string in ", image(s)) 100 | end 101 | method deref(reg, od) 102 | case reg of { 103 | Op.R_ABS: { 104 | if od < finstr then return data.word(od) 105 | else return code[od] 106 | } 107 | Op.R_IMM: { return od } 108 | Op.R_STACK: { return stack[bp+od] } 109 | default: { stop("deref region ", reg) } 110 | } 111 | end 112 | 113 | end 114 | class Data(d) 115 | method word(o) 116 | return d[1+o +: 8] 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /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 argv[1] ||:= ".j0" 5 | j0machine := j0machine() 6 | j0machine.init(filename) 7 | j0machine.interp() 8 | end 9 | -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /ch12/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ch3/dorrie.in: -------------------------------------------------------------------------------- 1 | Dorrie is 1 fine puppy -------------------------------------------------------------------------------- /ch3/dorrie.std: -------------------------------------------------------------------------------- 1 | token 1: Dorrie 2 | token 1: is 3 | token 2: 1 4 | token 1: fine 5 | token 1: puppy 6 | -------------------------------------------------------------------------------- /ch3/dorrie2.in: -------------------------------------------------------------------------------- 1 | Dorrie 2 | is 1 3 | fine puppy. 4 | -------------------------------------------------------------------------------- /ch3/dorrie2.std: -------------------------------------------------------------------------------- 1 | token 1 (line 1): Dorrie 2 | token 1 (line 2): is 3 | token 2 (line 2): 1 4 | token 1 (line 3): fine 5 | token 1 (line 3): puppy 6 | -------------------------------------------------------------------------------- /ch3/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch3/hello.std: -------------------------------------------------------------------------------- 1 | token 258:1 public 2 | token 269:1 class 3 | token 267:1 hello 4 | token 123:1 { 5 | token 258:2 public 6 | token 270:2 static 7 | token 265:2 void 8 | token 267:2 main 9 | token 40:2 ( 10 | token 267:2 String 11 | token 267:2 argv 12 | token 91:2 [ 13 | token 93:2 ] 14 | token 41:2 ) 15 | token 123:2 { 16 | token 267:3 System 17 | token 46:3 . 18 | token 267:3 out 19 | token 46:3 . 20 | token 267:3 println 21 | token 40:3 ( 22 | token 277:3 "hello, jzero!" 23 | token 41:3 ) 24 | token 59:3 ; 25 | token 125:4 } 26 | token 125:5 } 27 | -------------------------------------------------------------------------------- /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("token ", i, ":", yylval.lineno, " ", yytext) 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, 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 + ":"+yylineno+" " + 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, yycolno); 24 | return cat; 25 | } 26 | public static void newline() { 27 | yylineno++; yycolno = 1; 28 | } 29 | public static void whitespace() { 30 | yycolno += yytext().length(); 31 | } 32 | public static void comment() { 33 | } 34 | public static short ord(String s) { return (short)(s.charAt(0)); } 35 | } 36 | -------------------------------------------------------------------------------- /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/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 3 Linux makefile 3 | # 4 | # For testing purposes! 5 | # You do not need "make" to run the examples from Chapter 3. 6 | # I use "make" in order to regression-test and ensure that the 7 | # code runs. 8 | # 9 | 10 | all: u j 11 | 12 | u: simple-u simple2-u j0-u 13 | 14 | simple-u: 15 | uflex nnws.l 16 | unicon simple nnws 17 | ./simple dorrie.in >dorrie.out 18 | diff dorrie.out dorrie.std 19 | 20 | simple2-u: 21 | uflex nnws-tok.l 22 | unicon simple2 nnws-tok 23 | -./simple2 dorrie2.in >dorrie2.out 24 | diff dorrie2.out dorrie2.std 25 | 26 | j0-u: 27 | uflex javalex.l 28 | unicon j0 javalex 29 | ./j0 hello.java >hello.out 30 | diff hello.out hello.std 31 | 32 | j: simple-j simple2-j j0-j 33 | 34 | simple-j: 35 | jflex nnws.l 36 | javac simple.java 37 | java simple dorrie.in >dorrie.out 38 | diff dorrie.out dorrie.std 39 | 40 | simple2-j: 41 | jflex nnws-tok.l 42 | javac token.java 43 | javac simple2.java Yylex.java 44 | -java simple2 dorrie2.in >dorrie2.out 45 | diff dorrie2.out dorrie2.std 46 | 47 | j0-j: 48 | jflex javalex.l 49 | javac j0.java Yylex.java 50 | javac token.java parser.java 51 | java j0 hello.java > hello.out 52 | diff hello.out hello.std 53 | -------------------------------------------------------------------------------- /ch3/makefile.win: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 3 Windows makefile 3 | # 4 | # For testing purposes! 5 | # You do not need "make" to run the examples from Chapter 3. 6 | # I use "make" in order to regression-test and ensure that the 7 | # code runs. 8 | # 9 | 10 | all: u j 11 | 12 | u: simple-u simple2-u j0-u 13 | 14 | simple-u: 15 | uflex nnws.l 16 | unicon simple nnws 17 | simple dorrie.in >dorrie.out 18 | diff dorrie.out dorrie.std 19 | 20 | simple2-u: 21 | uflex nnws-tok.l 22 | unicon simple2 nnws-tok 23 | -simple2 dorrie2.in >dorrie2.out 24 | diff dorrie2.out dorrie2.std 25 | 26 | j0-u: 27 | uflex javalex.l 28 | unicon j0 javalex 29 | j0 hello.java >hello.out 30 | diff hello.out hello.std 31 | 32 | j: simple-j simple2-j j0-j 33 | 34 | simple-j: 35 | jflex nnws.l 36 | javac simple.java 37 | java simple dorrie.in >dorrie.out 38 | diff dorrie.out dorrie.std 39 | 40 | 41 | simple2-j: 42 | jflex nnws-tok.l 43 | javac token.java 44 | javac simple2.java Yylex.java 45 | -java simple2 dorrie2.in >dorrie2.out 46 | diff dorrie2.out dorrie2.std 47 | 48 | j0-j: 49 | jflex javalex.l 50 | javac j0.java Yylex.java 51 | javac token.java parser.java 52 | java j0 hello.java > hello.out 53 | diff hello.out hello.std 54 | -------------------------------------------------------------------------------- /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("token ", i, ": ", yytext) 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, 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 + 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, yycolno); 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, colno, ival; 5 | String sval; 6 | double dval; 7 | 8 | private String deEscape(String sin) { 9 | String sout = ""; 10 | sin = sin.substring(1,sin.length()-1); 11 | int i = 0; 12 | while (sin.length() > 0) { 13 | char c = sin.charAt(0); 14 | if (c == '\\') { 15 | sin = sin.substring(1); 16 | if (sin.length() < 1) 17 | j0.lexErr("malformed string literal"); 18 | else { 19 | c = sin.charAt(0); 20 | switch(c) { 21 | case 't': sout = sout + "\t"; break; 22 | case 'n': sout = sout + "\n"; break; 23 | default: j0.lexErr("unrecognized escape"); 24 | } 25 | } 26 | } 27 | else sout = sout + c; 28 | sin = sin.substring(1); 29 | } 30 | return sout; 31 | } 32 | 33 | public token(int c, String s, int l, int col) { 34 | cat = c; text = s; lineno = l; colno = col; 35 | switch (cat) { 36 | case parser.INTLIT: 37 | ival = Integer.parseInt(s); 38 | break; 39 | case parser.DOUBLELIT: 40 | dval = Double.parseDouble(s); 41 | break; 42 | case parser.STRINGLIT: 43 | sval = deEscape(s); 44 | break; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch4/dorrie.out: -------------------------------------------------------------------------------- 1 | no errors 2 | -------------------------------------------------------------------------------- /ch4/dorrie3.in: -------------------------------------------------------------------------------- 1 | Dorrie 1 Clint 0 -------------------------------------------------------------------------------- /ch4/dorrie3.std: -------------------------------------------------------------------------------- 1 | no errors 2 | -------------------------------------------------------------------------------- /ch4/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch4/hello.out: -------------------------------------------------------------------------------- 1 | no errors, 26 tokens parsed 2 | -------------------------------------------------------------------------------- /ch4/hello.std: -------------------------------------------------------------------------------- 1 | no errors, 26 tokens parsed 2 | -------------------------------------------------------------------------------- /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 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 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 | j0.par.yylval = new parserVal( 41 | new token(cat, yytext(), yylineno, yycolno)); 42 | count++; 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 | } 54 | -------------------------------------------------------------------------------- /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/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 4 Linux makefile 3 | # 4 | # For testing purposes! 5 | # You do not need "make" to run the examples from Chapter 4. 6 | # I use "make" in order to regression-test and ensure that the code runs. 7 | # 8 | # On Linux one may need to set the CLASSPATH by whatever syntax one now 9 | # uses for that. It varies by shell:L 10 | # 11 | # export CLASSPATH=.:.. 12 | # or just 13 | # export CLASSPATH=.. 14 | # or maybe 15 | # export CLASSPATH=/c/users/username/example 16 | # where that path is the directory above the ch4/ directory. 17 | # 18 | 19 | all: u j 20 | 21 | u: trivial-u j0-u 22 | 23 | trivial-u: 24 | uflex nnws.l 25 | iyacc -dd ns.y 26 | unicon trivial nnws ns ns_tab 27 | ./trivial dorrie3.in >dorrie.out 28 | diff dorrie.out dorrie3.std 29 | 30 | j0-u: 31 | uflex javalex.l 32 | iyacc -dd j0gram.y 33 | unicon j0 javalex j0gram j0gram_tab yyerror 34 | ./j0 hello.java >hello.out 35 | diff hello.out hello.std 36 | 37 | j: trivial-j j0-j 38 | 39 | trivial-j: 40 | export CLASSPATH=.:.. 41 | jflex nnws.l 42 | yacc -Jpackage=ch4 -Jyylex=ch4.lexer.yylex \ 43 | -Jyyerror=ch4.yyerror.yyerror ns.y 44 | javac trivial.java Yylex.java Parser.java lexer.java \ 45 | yyerror.java ParserVal.java 46 | java ch4.trivial dorrie3.in >dorrie.out 47 | diff dorrie.out dorrie3.std 48 | 49 | j0-j: 50 | export CLASSPATH=.:.. 51 | jflex javalex.l 52 | yacc -Jclass=parser -Jpackage=ch4 -Jyylex=ch4.j0.yylex\ 53 | -Jyyerror=ch4.yyerror.yyerror j0gram.y 54 | javac parser.java Yylex.java j0.java parserVal.java \ 55 | token.java yyerror.java 56 | java ch4.j0 hello.java > hello.out 57 | diff hello.out hello.std 58 | -------------------------------------------------------------------------------- /ch4/makefile.win: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 4 Windows makefile 3 | # 4 | # For testing purposes! 5 | # You do not need "make" to run the examples from Chapter 4. 6 | # I use "make" in order to regression-test and ensure that the code runs. 7 | # 8 | # On Windows one may need to set the CLASSPATH by whatever syntax one now 9 | # uses for that. It varies by shell. It used to be 10 | # 11 | # set CLASSPATH=".;c:\users\Alfrede Newmann" 12 | # 13 | # where you would change Afrede Newmann to say whatever path 14 | # leads to the directory above your ch4/ directory. 15 | # 16 | # On 10/31/23 with Java 21 I was able to just use 17 | # 18 | # set CLASSPATH=.. 19 | # 20 | 21 | all: u j 22 | 23 | u: trivial-u j0-u 24 | 25 | trivial-u: 26 | uflex nnws.l 27 | iyacc -dd ns.y 28 | unicon trivial nnws ns ns_tab 29 | trivial dorrie3.in >dorrie.out 30 | diff dorrie.out dorrie3.std 31 | 32 | j0-u: 33 | uflex javalex.l 34 | iyacc -dd j0gram.y 35 | unicon j0 javalex j0gram j0gram_tab yyerror 36 | j0 hello.java >hello.out 37 | diff hello.out hello.std 38 | 39 | j: trivial-j j0-j 40 | 41 | trivial-j: 42 | jflex nnws.l 43 | yacc -Jpackage=ch4 -Jyylex=ch4.lexer.yylex \ 44 | -Jyyerror=ch4.yyerror.yyerror ns.y 45 | javac trivial.java Yylex.java Parser.java lexer.java \ 46 | yyerror.java ParserVal.java 47 | java ch4.trivial dorrie3.in >dorrie.out 48 | diff dorrie.out dorrie3.std 49 | 50 | j0-j: 51 | jflex javalex.l 52 | yacc -Jclass=parser -Jpackage=ch4 -Jyylex=ch4.j0.yylex\ 53 | -Jyyerror=ch4.yyerror.yyerror j0gram.y 54 | javac parser.java Yylex.java j0.java parserVal.java \ 55 | token.java yyerror.java 56 | java ch4.j0 hello.java > hello.out 57 | diff hello.out hello.std 58 | -------------------------------------------------------------------------------- /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, colno; 6 | public token(int c, String s, int l, int col) { 7 | cat = c; text = s; lineno = l; colno = col; 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 | write(&errout, "line ", yylineno, " column ", yycolno, 3 | ", lexeme \"", yytext, "\": ", s) 4 | end 5 | -------------------------------------------------------------------------------- /ch4/yyerror.java: -------------------------------------------------------------------------------- 1 | package ch4; 2 | public class yyerror { 3 | public static void yyerror(String s) { 4 | System.err.println("line " + j0.yylineno + 5 | " column " + j0.yycolno + 6 | ", lexeme \"" + j0.yytext() + "\": " + s); 7 | System.exit(1); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch5/hello.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch5/hello.out: -------------------------------------------------------------------------------- 1 | 63 ClassDecl (1000): 2 2 | 6 hello (266): 1 3 | 62 ClassBody (1010): 1 4 | 59 MethodDecl (1380): 2 5 | 32 MethodHeader (1070): 2 6 | 14 void (264): 2 7 | 31 MethodDeclarator (1080): 2 8 | 16 main (266): 2 9 | 30 FormalParm (1100): 2 10 | 20 String (266): 2 11 | 27 VarDeclarator (1060): 1 12 | 22 argv (266): 2 13 | 58 Block (1200): 1 14 | 53 MethodCall (1290): 2 15 | 46 QualifiedName (1040): 2 16 | 41 QualifiedName (1040): 2 17 | 36 System (266): 3 18 | 40 out (266): 3 19 | 45 println (266): 3 20 | 50 "hello, jzero!" (273): 3 21 | no errors 22 | -------------------------------------------------------------------------------- /ch5/hello.std: -------------------------------------------------------------------------------- 1 | 63 ClassDecl (1000): 2 2 | 6 hello (266): 1 3 | 62 ClassBody (1010): 1 4 | 59 MethodDecl (1380): 2 5 | 32 MethodHeader (1070): 2 6 | 14 void (264): 2 7 | 31 MethodDeclarator (1080): 2 8 | 16 main (266): 2 9 | 30 FormalParm (1100): 2 10 | 20 String (266): 2 11 | 27 VarDeclarator (1060): 1 12 | 22 argv (266): 2 13 | 58 Block (1200): 1 14 | 53 MethodCall (1290): 2 15 | 46 QualifiedName (1040): 2 16 | 41 QualifiedName (1040): 2 17 | 36 System (266): 3 18 | 40 out (266): 3 19 | 45 println (266): 3 20 | 50 "hello, jzero!" (273): 3 21 | no errors 22 | -------------------------------------------------------------------------------- /ch5/helloerror.java: -------------------------------------------------------------------------------- 1 | public class hello { 2 | public static void main(String argv[]) { 3 | System.out.println("hello, jzero!") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch5/hellostd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Build-your-own-Programming-Language-Second-Edition/36b60db1a08b39d7695b20eca9aece26babf1c00/ch5/hellostd.png -------------------------------------------------------------------------------- /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 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 5 Linux makefile, 3 | # tested on MSYS2 Mingw bash shell. 4 | # 5 | # On Linux one may need to set the CLASSPATH by whatever syntax one now 6 | # uses for that. It varies by shell: 7 | # 8 | # export CLASSPATH=.:.. 9 | # or just 10 | # export CLASSPATH=.. 11 | # or maybe 12 | # export CLASSPATH=/c/users/username/example 13 | # where that path is the directory above the ch5/ directory. 14 | # 15 | 16 | all: u j 17 | 18 | LYU=javalex.u j0gram.u j0gram_tab.u 19 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) 20 | unicon: j0 21 | %.u : %.icn 22 | unicon -c $< 23 | 24 | u: unicon 25 | ./j0 hello.java >hello.out 26 | diff hello.out hello.std 27 | dot -Tpng hello.java.dot >hello.png 28 | diff hellostd.png hello.png 29 | j0: $(U) 30 | unicon $(U) 31 | javalex.icn: javalex.l 32 | uflex javalex.l 33 | j0gram.icn j0gram_tab.icn: j0gram.y 34 | iyacc -dd j0gram.y 35 | 36 | 37 | # A typical run might use 38 | # set CLASSPATH=".;c:\users\username\byopl" 39 | # in order to run from c:\users\username\byopl\ch5 40 | BYSRC=parser.java parserVal.java Yylex.java 41 | JSRC=j0.java tree.java token.java yyerror.java serial.java $(BYSRC) 42 | BYJOPTS= -Jclass=parser -Jpackage=ch5 43 | BYJIMPS= -Jyylex=ch5.j0.yylex -Jyyerror=ch5.yyerror.yyerror 44 | java: j0.class 45 | 46 | j: java 47 | java ch5.j0 hello.java >hello.out 48 | diff hello.out hello.std 49 | dot -Tpng hello.java.dot >hello.png 50 | diff hellostd.png hello.png 51 | 52 | j0.class: $(JSRC) 53 | javac $(JSRC) 54 | parser.java parserVal.java: j0gram.y 55 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 56 | Yylex.java: javalex.l 57 | jflex javalex.l 58 | 59 | -------------------------------------------------------------------------------- /ch5/makefile.win: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 5 Windows makefile, 3 | # tested on Windows Command Prompt. 4 | # 5 | # On Windows one may need to set the CLASSPATH by whatever syntax one now 6 | # uses for that. It varies by shell. It used to be 7 | # 8 | # set CLASSPATH=".;c:\users\username" 9 | # or maybe 10 | # set CLASSPATH=c:\users\username 11 | # 12 | # where you would change username to say whatever path leads to the directory 13 | # above your ch5/ directory. 14 | # 15 | 16 | all: u j 17 | 18 | LYU=javalex.u j0gram.u j0gram_tab.u 19 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) 20 | unicon: j0 21 | %.u : %.icn 22 | unicon -c $< 23 | 24 | u: unicon 25 | j0 hello.java >hello.out 26 | diff hello.out hello.std 27 | dot -Tpng -Gdpi=300 hello.java.dot >hello.png 28 | -diff hellostd.png hello.png 29 | rem you will have to eyeball hello.png to see if it looks correct 30 | j0: $(U) 31 | unicon $(U) 32 | javalex.icn: javalex.l 33 | uflex javalex.l 34 | j0gram.icn j0gram_tab.icn: j0gram.y 35 | iyacc -dd j0gram.y 36 | 37 | 38 | # A typical run used to use 39 | # set CLASSPATH=".;c:\users\username\byopl" 40 | # in order to run from c:\users\username\byopl\ch5 41 | # although most recently I had to just say 42 | # set CLASSPATH=c:\users\username\byopl 43 | # with no double-quotes or anything. 44 | # 45 | 46 | BYSRC=parser.java parserVal.java Yylex.java 47 | JSRC=j0.java tree.java token.java yyerror.java serial.java $(BYSRC) 48 | BYJOPTS= -Jclass=parser -Jpackage=ch5 49 | BYJIMPS= -Jyylex=ch5.j0.yylex -Jyyerror=ch5.yyerror.yyerror 50 | java: j0.class 51 | 52 | j: java 53 | java ch5.j0 hello.java >hello.out 54 | diff hello.out hello.std 55 | dot -Tpng -Gdpi=300 hello.java.dot >hello.png 56 | -diff hellostd.png hello.png 57 | rem you will have to eyeball hello.png to see if it looks correct 58 | 59 | j0.class: $(JSRC) 60 | javac $(JSRC) 61 | parser.java parserVal.java: j0gram.y 62 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 63 | Yylex.java: javalex.l 64 | jflex javalex.l 65 | -------------------------------------------------------------------------------- /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(){ 5 | serial++; return serial; } 6 | } 7 | -------------------------------------------------------------------------------- /ch5/token.icn: -------------------------------------------------------------------------------- 1 | class token(cat, text, lineno, colno, id, 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 | id := serial.getid() 22 | case cat of { 23 | parser.INTLIT: { ival := integer(text) } 24 | parser.DOUBLELIT: { dval := real(text) } 25 | parser.STRINGLIT: { sval := deEscape(text) } 26 | } 27 | end 28 | -------------------------------------------------------------------------------- /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+1] 38 | print_branch(pw) 39 | writes(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 | writes(pw, "N",id," [shape=box label=\"", 46 | pretty_print_name()); 47 | if \tok then writes(pw, " id ", tok.id) 48 | write(pw, "\"];"); 49 | end 50 | method escape(s) 51 | if s[1] == "\"" then 52 | return "\\" || s[1:-1] || "\\\"" 53 | else return s 54 | end 55 | method pretty_print_name() 56 | if /tok then return sym || "#" || (rule%10) 57 | else return escape(tok.text) || ":" || tok.cat 58 | end 59 | 60 | initially (s,r,x[]) 61 | id := serial.getid(); sym := s; rule := r 62 | if type(x[1]) == "token__state" then { 63 | nkids := 0; tok := x[1] 64 | } else { 65 | nkids := *x 66 | kids := x 67 | } 68 | end 69 | -------------------------------------------------------------------------------- /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(" id %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 parser par; 6 | public static symtab global_st; 7 | public static void main(String argv[]) throws Exception { 8 | init(argv[0]); 9 | par = new 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 | 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 | symtab out_st, System_st; 72 | global_st = new symtab("global"); 73 | System_st = new symtab("class"); 74 | out_st = new 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 | # Build Your Own Programming Language, 2nd edition, Chapter 6 Linux makefile, 3 | # tested on MSYS2 Mingw bash shell. 4 | # 5 | # On Linux one may need to set the CLASSPATH by whatever syntax one now 6 | # uses for that. It varies by shell: 7 | # 8 | # export CLASSPATH=.:.. 9 | # or just 10 | # export CLASSPATH=.. 11 | # or maybe 12 | # export CLASSPATH=/c/users/username/example 13 | # where that path is the directory above the ch6/ directory. 14 | # 15 | 16 | all: java unicon 17 | 18 | LYU=javalex.u j0gram.u j0gram_tab.u 19 | STU=symtab.u symtab_entry.u 20 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) 21 | unicon: j0 22 | %.u : %.icn 23 | unicon -c $< 24 | j0: $(U) 25 | unicon $(U) 26 | javalex.icn: javalex.l 27 | uflex javalex.l 28 | j0gram.icn j0gram_tab.icn: j0gram.y 29 | iyacc -dd j0gram.y 30 | 31 | # A typical run might use 32 | # set CLASSPATH=".;c:\users\username\byopl" 33 | # in order to run from c:\users\username\byopl\ch5 34 | LYSRC=Yylex.java parser.java parserVal.java 35 | STJ=symtab.java symtab_entry.java 36 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) 37 | BYJOPTS= -Jclass=parser -Jpackage=ch6 38 | BYJIMPS= -Jyylex=ch6.j0.yylex -Jyyerror=ch6.yyerror.yyerror 39 | java: j0.class 40 | 41 | j: java 42 | java ch6.j0 hello.java 43 | dot -Tpng hello.java.dot >hello.png 44 | 45 | j0.class: $(JSRC) 46 | javac $(JSRC) 47 | parser.java parserVal.java: j0gram.y 48 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 49 | Yylex.java: javalex.l 50 | jflex javalex.l 51 | 52 | -------------------------------------------------------------------------------- /ch6/makefile.win: -------------------------------------------------------------------------------- 1 | # 2 | # Build Your Own Programming Language, 2nd edition, Chapter 6 Windows makefile, 3 | # tested on Windows Command Prompt. 4 | # 5 | # On Windows one may need to set the CLASSPATH by whatever syntax one now 6 | # uses for that. It varies by shell. It used to be 7 | # 8 | # set CLASSPATH=".;c:\users\username" 9 | # or maybe 10 | # set CLASSPATH=c:\users\username 11 | # 12 | # where you would change username to say whatever path leads to the directory 13 | # above your ch6/ directory. 14 | # 15 | 16 | all: java unicon 17 | 18 | LYU=javalex.u j0gram.u j0gram_tab.u 19 | STU=symtab.u symtab_entry.u 20 | U=j0.u token.u tree.u serial.u yyerror.u $(LYU) $(STU) 21 | unicon: j0 22 | %.u : %.icn 23 | unicon -c $< 24 | u: unicon 25 | j0 hello.java >hello.out 26 | 27 | # dot -Tpng hello.java.dot >hello.png 28 | 29 | j0: $(U) 30 | unicon $(U) 31 | javalex.icn: javalex.l 32 | uflex javalex.l 33 | j0gram.icn j0gram_tab.icn: j0gram.y 34 | iyacc -dd j0gram.y 35 | 36 | # A typical run might use 37 | # set CLASSPATH=".;c:\users\username\byopl" 38 | # in order to run from c:\users\username\byopl\ch5 39 | LYSRC=Yylex.java parser.java parserVal.java 40 | STJ=symtab.java symtab_entry.java 41 | JSRC=j0.java token.java yyerror.java tree.java serial.java $(LYSRC) $(STJ) 42 | BYJOPTS= -Jclass=parser -Jpackage=ch6 43 | BYJIMPS= -Jyylex=ch6.j0.yylex -Jyyerror=ch6.yyerror.yyerror 44 | java: j0.class 45 | 46 | j: java 47 | java ch6.j0 hello.java 48 | 49 | # dot -Tpng hello.java.dot >hello.png 50 | 51 | j0.class: $(JSRC) 52 | javac $(JSRC) 53 | parser.java parserVal.java: j0gram.y 54 | yacc $(BYJOPTS) $(BYJIMPS) j0gram.y 55 | Yylex.java: javalex.l 56 | jflex javalex.l 57 | 58 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/parserVal.java: -------------------------------------------------------------------------------- 1 | //############################################# 2 | //## file: parser.java 3 | //## Generated by Byacc/j 4 | //############################################# 5 | package ch8; 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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------