diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f4c2b81
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 deryckb
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Triangle.AbstractMachine.Disassembler/.gitignore b/Triangle.AbstractMachine.Disassembler/.gitignore
new file mode 100644
index 0000000..8c107fe
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/.classpath
+/build/
diff --git a/Triangle.AbstractMachine.Disassembler/.project b/Triangle.AbstractMachine.Disassembler/.project
new file mode 100644
index 0000000..7024cd7
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/.project
@@ -0,0 +1,23 @@
+
+
+ Triangle.AbstractMachine.Disassembler
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/Triangle.AbstractMachine.Disassembler/build.gradle b/Triangle.AbstractMachine.Disassembler/build.gradle
new file mode 100644
index 0000000..90e01e7
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'java'
+apply plugin: 'application'
+
+sourceCompatibility = 11
+
+dependencies {
+ implementation project(':Triangle.AbstractMachine')
+}
+
+application {
+ mainClass = 'Triangle.AbstractMachine.Disassembler'
+}
\ No newline at end of file
diff --git a/Triangle.AbstractMachine.Disassembler/pom.xml b/Triangle.AbstractMachine.Disassembler/pom.xml
new file mode 100644
index 0000000..847d0fc
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/pom.xml
@@ -0,0 +1,18 @@
+
+ 4.0.0
+ triangle-disassembler
+
+ triangle.tools
+ triangle-tools
+ 2.1
+ ../
+
+
+
+ triangle.tools
+ triangle-abstractmachine
+ 2.1
+
+
+
diff --git a/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java b/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java
new file mode 100644
index 0000000..ca94c79
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java
@@ -0,0 +1,351 @@
+/*
+ * @(#)Disassembler.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractMachine;
+
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Disassembles the TAM code in the given file, and displays the instructions on
+ * standard output.
+ *
+ * For example:
+ *
+ *
+ * java TAM.Disassembler obj.tam
+ *
+ *
+ *
+ * Copyright 1991 David A. Watt, University of Glasgow
+ * Copyright 1998 Deryck F. Brown, The Robert Gordon University
+ *
+ *
+ */
+
+public class Disassembler {
+
+ static String objectName;
+
+ static int CT;
+
+ /**
+ * Writes the r-field of an instruction in the form "lregr", where l and
+ * r are the bracket characters to use.
+ *
+ * @param leftbracket the character to print before the register.
+ * @param r the number of the register.
+ * @param rightbracket the character to print after the register.
+ */
+ private static void writeR(char leftbracket, Register r, char rightbracket) {
+
+ System.out.print(leftbracket);
+ System.out.print(r.toString());
+ System.out.print(rightbracket);
+ }
+
+ private static void writeR(char leftBracket, int r, char rightBracket) {
+ var register = Register.values()[r];
+ writeR(leftBracket, register, rightBracket);
+ }
+
+ /**
+ * Writes a void n-field of an instruction.
+ */
+ private static void blankN() {
+ System.out.print(" ");
+ }
+
+ // Writes the n-field of an instruction.
+ /**
+ * Writes the n-field of an instruction in the form "(n)".
+ *
+ * @param n the integer to write.
+ */
+ private static void writeN(int n) {
+ System.out.print("(" + n + ") ");
+ if (n < 10) {
+ System.out.print(" ");
+ } else if (n < 100) {
+ System.out.print(" ");
+ }
+ }
+
+ /**
+ * Writes the d-field of an instruction.
+ *
+ * @param d the integer to write.
+ */
+ private static void writeD(int d) {
+ System.out.print(d);
+ }
+
+ /**
+ * Writes the name of primitive routine with relative address d.
+ *
+ * @param d the displacement of the primitive routine.
+ */
+ private static void writePrimitive(int d) {
+ var primitive = Primitive.values()[d];
+ switch (primitive) {
+ case ID:
+ System.out.print("id ");
+ break;
+ case NOT:
+ System.out.print("not ");
+ break;
+ case AND:
+ System.out.print("and ");
+ break;
+ case OR:
+ System.out.print("or ");
+ break;
+ case SUCC:
+ System.out.print("succ ");
+ break;
+ case PRED:
+ System.out.print("pred ");
+ break;
+ case NEG:
+ System.out.print("neg ");
+ break;
+ case ADD:
+ System.out.print("add ");
+ break;
+ case SUB:
+ System.out.print("sub ");
+ break;
+ case MULT:
+ System.out.print("mult ");
+ break;
+ case DIV:
+ System.out.print("div ");
+ break;
+ case MOD:
+ System.out.print("mod ");
+ break;
+ case LT:
+ System.out.print("lt ");
+ break;
+ case LE:
+ System.out.print("le ");
+ break;
+ case GE:
+ System.out.print("ge ");
+ break;
+ case GT:
+ System.out.print("gt ");
+ break;
+ case EQ:
+ System.out.print("eq ");
+ break;
+ case NE:
+ System.out.print("ne ");
+ break;
+ case EOL:
+ System.out.print("eol ");
+ break;
+ case EOF:
+ System.out.print("eof ");
+ break;
+ case GET:
+ System.out.print("get ");
+ break;
+ case PUT:
+ System.out.print("put ");
+ break;
+ case GETEOL:
+ System.out.print("geteol ");
+ break;
+ case PUTEOL:
+ System.out.print("puteol ");
+ break;
+ case GETINT:
+ System.out.print("getint ");
+ break;
+ case PUTINT:
+ System.out.print("putint ");
+ break;
+ case NEW:
+ System.out.print("new ");
+ break;
+ case DISPOSE:
+ System.out.print("dispose ");
+ break;
+ }
+ }
+
+ /**
+ * Writes the given instruction in assembly-code format.
+ *
+ * @param instr the instruction to display.
+ */
+ private static void writeInstruction(Instruction instr) {
+
+ switch (instr.opCode) {
+ case LOAD:
+ System.out.print("LOAD ");
+ writeN(instr.length);
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ break;
+
+ case LOADA:
+ System.out.print("LOADA ");
+ blankN();
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ break;
+
+ case LOADI:
+ System.out.print("LOADI ");
+ writeN(instr.length);
+ break;
+
+ case LOADL:
+ System.out.print("LOADL ");
+ blankN();
+ writeD(instr.operand);
+ break;
+
+ case STORE:
+ System.out.print("STORE ");
+ writeN(instr.length);
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ break;
+
+ case STOREI:
+ System.out.print("STOREI");
+ writeN(instr.length);
+ break;
+
+ case CALL:
+ System.out.print("CALL ");
+ if (instr.register == Register.PB) {
+ blankN();
+ writePrimitive(instr.operand);
+ } else {
+ writeR('(', instr.length, ')');
+ System.out.print(" ");
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ }
+ break;
+
+ case CALLI:
+ System.out.print("CALLI ");
+ break;
+
+ case RETURN:
+ System.out.print("RETURN");
+ writeN(instr.length);
+ writeD(instr.operand);
+ break;
+
+ case PUSH:
+ System.out.print("PUSH ");
+ blankN();
+ writeD(instr.operand);
+ break;
+
+ case POP:
+ System.out.print("POP ");
+ writeN(instr.length);
+ writeD(instr.operand);
+ break;
+
+ case JUMP:
+ System.out.print("JUMP ");
+ blankN();
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ break;
+
+ case JUMPI:
+ System.out.print("JUMPI ");
+ break;
+
+ case JUMPIF:
+ System.out.print("JUMPIF");
+ writeN(instr.length);
+ writeD(instr.operand);
+ writeR('[', instr.register, ']');
+ break;
+
+ case HALT:
+ System.out.print("HALT ");
+ }
+ }
+
+ /**
+ * Writes all instructions of the program in code store.
+ */
+ private static void disassembleProgram() {
+ for (int addr = Machine.CB; addr < CT; addr++) {
+ System.out.print(addr + ": ");
+ writeInstruction(Machine.code[addr]);
+ System.out.println();
+ }
+ }
+
+ // LOADING
+
+ /**
+ * Loads the TAM object program into code store from the named file.
+ *
+ * @param objectName the name of the file containing the program.
+ */
+ static void loadObjectProgram(String objectName) {
+
+ var finished = false;
+
+ try (var objectFile = new FileInputStream(objectName)) {
+ var objectStream = new DataInputStream(objectFile);
+ var addr = Machine.CB;
+ while (!finished) {
+ Machine.code[addr] = Instruction.read(objectStream);
+ if (Machine.code[addr] == null) {
+ finished = true;
+ } else {
+ addr = addr + 1;
+ }
+ }
+ CT = addr;
+ } catch (FileNotFoundException s) {
+ CT = Machine.CB;
+ System.err.println("Error opening object file: " + s);
+ } catch (IOException s) {
+ CT = Machine.CB;
+ System.err.println("Error reading object file: " + s);
+ }
+ }
+
+ // DISASSEMBLE
+
+ public static void main(String[] args) {
+ System.out.println("********** TAM Disassembler (Sun Version 2.1) **********");
+
+ if (args.length == 1) {
+ objectName = args[0];
+ } else {
+ objectName = "obj.tam";
+ }
+
+ loadObjectProgram(objectName);
+ disassembleProgram();
+ }
+}
diff --git a/Triangle.AbstractMachine.Interpreter/.gitignore b/Triangle.AbstractMachine.Interpreter/.gitignore
new file mode 100644
index 0000000..8c107fe
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/.classpath
+/build/
diff --git a/Triangle.AbstractMachine.Interpreter/.project b/Triangle.AbstractMachine.Interpreter/.project
new file mode 100644
index 0000000..a22beaa
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/.project
@@ -0,0 +1,23 @@
+
+
+ Triangle.AbstractMachine.Interpreter
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/Triangle.AbstractMachine.Interpreter/build.gradle b/Triangle.AbstractMachine.Interpreter/build.gradle
new file mode 100644
index 0000000..38c7835
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'java'
+apply plugin: 'application'
+
+sourceCompatibility = 11
+
+dependencies {
+ implementation project(':Triangle.AbstractMachine')
+}
+
+application {
+ mainClass = 'Triangle.AbstractMachine.Interpreter'
+}
\ No newline at end of file
diff --git a/Triangle.AbstractMachine.Interpreter/pom.xml b/Triangle.AbstractMachine.Interpreter/pom.xml
new file mode 100644
index 0000000..551e835
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/pom.xml
@@ -0,0 +1,18 @@
+
+ 4.0.0
+ triangle-interpreter
+
+ triangle.tools
+ triangle-tools
+ 2.1
+ ../
+
+
+
+ triangle.tools
+ triangle-abstractmachine
+ 2.1
+
+
+
diff --git a/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java b/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java
new file mode 100644
index 0000000..96b10c5
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java
@@ -0,0 +1,645 @@
+/*
+ * @(#)Interpreter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractMachine;
+
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class Interpreter {
+
+ static long startTimeNanos = 0;
+
+ static String objectName;
+
+ // DATA STORE
+
+ static int[] data = new int[1024];
+
+ // DATA STORE REGISTERS AND OTHER REGISTERS
+
+ final static int CB = 0, SB = 0, HB = 1024; // = upper bound of data array + 1
+
+ static int CT, CP, ST, HT, LB, status;
+
+ // status values
+ final static int running = 0, halted = 1, failedDataStoreFull = 2, failedInvalidCodeAddress = 3,
+ failedInvalidInstruction = 4, failedOverflow = 5, failedZeroDivide = 6, failedIOError = 7;
+
+ static long accumulator;
+
+ static int content(int r) {
+ var register = Register.values()[r];
+ return content(register);
+ }
+
+ static int content(Register r) {
+ // Returns the current content of register r,
+ // even if r is one of the pseudo-registers L1..L6.
+
+ switch (r) {
+ case CB:
+ return CB;
+ case CT:
+ return CT;
+ case PB:
+ return Machine.PB;
+ case PT:
+ return Machine.PT;
+ case SB:
+ return SB;
+ case ST:
+ return ST;
+ case HB:
+ return HB;
+ case HT:
+ return HT;
+ case LB:
+ return LB;
+ case L1:
+ return data[LB];
+ case L2:
+ return data[data[LB]];
+ case L3:
+ return data[data[data[LB]]];
+ case L4:
+ return data[data[data[data[LB]]]];
+ case L5:
+ return data[data[data[data[data[LB]]]]];
+ case L6:
+ return data[data[data[data[data[data[LB]]]]]];
+ case CP:
+ return CP;
+ default:
+ return 0;
+ }
+ }
+
+ // PROGRAM STATUS
+
+ static void dump() {
+ // Writes a summary of the machine state.
+
+ System.out.println("");
+ System.out.println("State of data store and registers:");
+ System.out.println("");
+ if (HT == HB) {
+ System.out.println(" |--------| (heap is empty)");
+ } else {
+ System.out.println(" HB-->");
+ System.out.println(" |--------|");
+ for (var addr = HB - 1; addr >= HT; addr--) {
+ System.out.print(addr + ":");
+ if (addr == HT) {
+ System.out.print(" HT-->");
+ } else {
+ System.out.print(" ");
+ }
+ System.out.println("|" + data[addr] + "|");
+ }
+ System.out.println(" |--------|");
+ }
+ System.out.println(" |////////|");
+ System.out.println(" |////////|");
+ if (ST == SB) {
+ System.out.println(" |--------| (stack is empty)");
+ } else {
+ var dynamicLink = LB;
+ var staticLink = LB;
+ var localRegNum = Register.LB;
+ System.out.println(" ST--> |////////|");
+ System.out.println(" |--------|");
+ for (var addr = ST - 1; addr >= SB; addr--) {
+ System.out.print(addr + ":");
+ if (addr == SB) {
+ System.out.print(" SB-->");
+ } else if (addr == staticLink) {
+ switch (localRegNum) {
+ case LB:
+ System.out.print(" LB-->");
+ break;
+ case L1:
+ System.out.print(" L1-->");
+ break;
+ case L2:
+ System.out.print(" L2-->");
+ break;
+ case L3:
+ System.out.print(" L3-->");
+ break;
+ case L4:
+ System.out.print(" L4-->");
+ break;
+ case L5:
+ System.out.print(" L5-->");
+ break;
+ case L6:
+ System.out.print(" L6-->");
+ break;
+ default:
+ break;
+ }
+ staticLink = data[addr];
+ localRegNum = Register.values()[localRegNum.ordinal() + 1];
+ } else {
+ System.out.print(" ");
+ }
+ if (addr == dynamicLink && dynamicLink != SB) {
+ System.out.print("|SL=" + data[addr] + "|");
+ } else if (addr == dynamicLink + 1 && dynamicLink != SB) {
+ System.out.print("|DL=" + data[addr] + "|");
+ } else if (addr == dynamicLink + 2 && dynamicLink != SB) {
+ System.out.print("|RA=" + data[addr] + "|");
+ } else {
+ System.out.print("|" + data[addr] + "|");
+ }
+ System.out.println("");
+ if (addr == dynamicLink) {
+ System.out.println(" |--------|");
+ dynamicLink = data[addr + 1];
+ }
+ }
+ }
+ System.out.println("");
+ }
+
+ static void showStatus() {
+ // Writes an indication of whether and why the program has terminated.
+ System.out.println("");
+ switch (status) {
+ case running:
+ System.out.println("Program is running.");
+ break;
+ case halted:
+ System.out.println("Program has halted normally.");
+ System.out.println("Total execution time (ns): " + (System.nanoTime() - startTimeNanos));
+ break;
+ case failedDataStoreFull:
+ System.out.println("Program has failed due to exhaustion of Data Store.");
+ break;
+ case failedInvalidCodeAddress:
+ System.out.println("Program has failed due to an invalid code address.");
+ break;
+ case failedInvalidInstruction:
+ System.out.println("Program has failed due to an invalid instruction.");
+ break;
+ case failedOverflow:
+ System.out.println("Program has failed due to overflow.");
+ break;
+ case failedZeroDivide:
+ System.out.println("Program has failed due to division by zero.");
+ break;
+ case failedIOError:
+ System.out.println("Program has failed due to an IO error.");
+ break;
+ }
+ if (status != halted) {
+ dump();
+ }
+ }
+
+ // INTERPRETATION
+
+ static void checkSpace(int spaceNeeded) {
+ // Signals failure if there is not enough space to expand the stack or
+ // heap by spaceNeeded.
+
+ if (HT - ST < spaceNeeded) {
+ status = failedDataStoreFull;
+ }
+ }
+
+ static boolean isTrue(int datum) {
+ // Tests whether the given datum represents true.
+ return (datum == Machine.trueRep);
+ }
+
+ static boolean equal(int size, int addr1, int addr2) {
+ // Tests whether two multi-word objects are equal, given their common
+ // size and their base addresses.
+
+ boolean eq;
+ int index;
+
+ eq = true;
+ index = 0;
+ while (eq && (index < size)) {
+ if (data[addr1 + index] == data[addr2 + index]) {
+ index = index + 1;
+ } else {
+ eq = false;
+ }
+ }
+
+ return eq;
+ }
+
+ static int overflowChecked(long datum) {
+ // Signals failure if the datum is too large to fit into a single word,
+ // otherwise returns the datum as a single word.
+
+ if ((-Machine.maxintRep <= datum) && (datum <= Machine.maxintRep)) {
+ return (int) datum;
+ } else {
+ status = failedOverflow;
+ return 0;
+ }
+ }
+
+ static int toInt(boolean b) {
+ return b ? Machine.trueRep : Machine.falseRep;
+ }
+
+ static int currentChar;
+
+ static int readInt() throws java.io.IOException {
+ int temp = 0;
+ int sign = 1;
+
+ do {
+ currentChar = System.in.read();
+ } while (Character.isWhitespace((char) currentChar));
+
+ if ((currentChar == '-') || (currentChar == '+')) {
+ do {
+ sign = (currentChar == '-') ? -1 : 1;
+ currentChar = System.in.read();
+ } while ((currentChar == '-') || currentChar == '+');
+ }
+
+ if (Character.isDigit((char) currentChar)) {
+ do {
+ temp = temp * 10 + (currentChar - '0');
+ currentChar = System.in.read();
+ } while (Character.isDigit((char) currentChar));
+ }
+
+ return sign * temp;
+ }
+
+ static void callPrimitive(int primitiveDisplacement) {
+ // Invokes the given primitive routine.
+
+ int addr, size;
+ char ch;
+
+ var primitive = Primitive.values()[primitiveDisplacement];
+ switch (primitive) {
+ case ID:
+ break; // nothing to be done
+ case NOT:
+ data[ST - 1] = toInt(!isTrue(data[ST - 1]));
+ break;
+ case AND:
+ ST = ST - 1;
+ data[ST - 1] = toInt(isTrue(data[ST - 1]) & isTrue(data[ST]));
+ break;
+ case OR:
+ ST = ST - 1;
+ data[ST - 1] = toInt(isTrue(data[ST - 1]) | isTrue(data[ST]));
+ break;
+ case SUCC:
+ data[ST - 1] = overflowChecked(data[ST - 1] + 1);
+ break;
+ case PRED:
+ data[ST - 1] = overflowChecked(data[ST - 1] - 1);
+ break;
+ case NEG:
+ data[ST - 1] = -data[ST - 1];
+ break;
+ case ADD:
+ ST = ST - 1;
+ accumulator = data[ST - 1];
+ data[ST - 1] = overflowChecked(accumulator + data[ST]);
+ break;
+ case SUB:
+ ST = ST - 1;
+ accumulator = data[ST - 1];
+ data[ST - 1] = overflowChecked(accumulator - data[ST]);
+ break;
+ case MULT:
+ ST = ST - 1;
+ accumulator = data[ST - 1];
+ data[ST - 1] = overflowChecked(accumulator * data[ST]);
+ break;
+ case DIV:
+ ST = ST - 1;
+ accumulator = data[ST - 1];
+ if (data[ST] != 0) {
+ data[ST - 1] = (int) (accumulator / data[ST]);
+ } else {
+ status = failedZeroDivide;
+ }
+ break;
+ case MOD:
+ ST = ST - 1;
+ accumulator = data[ST - 1];
+ if (data[ST] != 0) {
+ data[ST - 1] = (int) (accumulator % data[ST]);
+ } else {
+ status = failedZeroDivide;
+ }
+ break;
+ case LT:
+ ST = ST - 1;
+ data[ST - 1] = toInt(data[ST - 1] < data[ST]);
+ break;
+ case LE:
+ ST = ST - 1;
+ data[ST - 1] = toInt(data[ST - 1] <= data[ST]);
+ break;
+ case GE:
+ ST = ST - 1;
+ data[ST - 1] = toInt(data[ST - 1] >= data[ST]);
+ break;
+ case GT:
+ ST = ST - 1;
+ data[ST - 1] = toInt(data[ST - 1] > data[ST]);
+ break;
+ case EQ:
+ size = data[ST - 1]; // size of each comparand
+ ST = ST - 2 * size;
+ data[ST - 1] = toInt(equal(size, ST - 1, ST - 1 + size));
+ break;
+ case NE:
+ size = data[ST - 1]; // size of each comparand
+ ST = ST - 2 * size;
+ data[ST - 1] = toInt(!equal(size, ST - 1, ST - 1 + size));
+ break;
+ case EOL:
+ data[ST] = toInt(currentChar == '\n');
+ ST = ST + 1;
+ break;
+ case EOF:
+ data[ST] = toInt(currentChar == -1);
+ ST = ST + 1;
+ break;
+ case GET:
+ ST = ST - 1;
+ addr = data[ST];
+ try {
+ currentChar = System.in.read();
+ } catch (java.io.IOException s) {
+ status = failedIOError;
+ }
+ data[addr] = currentChar;
+ break;
+ case PUT:
+ ST = ST - 1;
+ ch = (char) data[ST];
+ System.out.print(ch);
+ break;
+ case GETEOL:
+ try {
+ while ((currentChar = System.in.read()) != '\n')
+ ;
+ } catch (java.io.IOException s) {
+ status = failedIOError;
+ }
+ break;
+ case PUTEOL:
+ System.out.println("");
+ break;
+ case GETINT:
+ ST = ST - 1;
+ addr = data[ST];
+ try {
+ accumulator = readInt();
+ } catch (java.io.IOException s) {
+ status = failedIOError;
+ }
+ data[addr] = (int) accumulator;
+ break;
+ case PUTINT:
+ ST = ST - 1;
+ accumulator = data[ST];
+ System.out.print(accumulator);
+ break;
+ case NEW:
+ size = data[ST - 1];
+ checkSpace(size);
+ HT = HT - size;
+ data[ST - 1] = HT;
+ break;
+ case DISPOSE:
+ ST = ST - 1; // no action taken at present
+ break;
+ }
+ }
+
+ static void interpretProgram() {
+ // Runs the program in code store.
+
+ Instruction currentInstr;
+
+ // Initialize registers ...
+ ST = SB;
+ HT = HB;
+ LB = SB;
+ CP = CB;
+ status = running;
+ do {
+ // Fetch instruction ...
+ currentInstr = Machine.code[CP];
+ // Decode instruction ...
+ var op = currentInstr.opCode;
+ var r = currentInstr.register;
+ var n = currentInstr.length;
+ var d = currentInstr.operand;
+ int addr;
+
+ // Execute instruction ...
+ switch (op) {
+ case LOAD:
+ addr = d + content(r);
+ checkSpace(n);
+ for (var index = 0; index < n; index++) {
+ data[ST + index] = data[addr + index];
+ }
+ ST = ST + n;
+ CP = CP + 1;
+ break;
+ case LOADA:
+ addr = d + content(r);
+ checkSpace(1);
+ data[ST] = addr;
+ ST = ST + 1;
+ CP = CP + 1;
+ break;
+ case LOADI:
+ ST = ST - 1;
+ addr = data[ST];
+ checkSpace(n);
+ for (var index = 0; index < n; index++) {
+ data[ST + index] = data[addr + index];
+ }
+ ST = ST + n;
+ CP = CP + 1;
+ break;
+ case LOADL:
+ checkSpace(1);
+ data[ST] = d;
+ ST = ST + 1;
+ CP = CP + 1;
+ break;
+ case STORE:
+ addr = d + content(r);
+ ST = ST - n;
+ for (var index = 0; index < n; index++) {
+ data[addr + index] = data[ST + index];
+ }
+ CP = CP + 1;
+ break;
+ case STOREI:
+ ST = ST - 1;
+ addr = data[ST];
+ ST = ST - n;
+ for (var index = 0; index < n; index++) {
+ data[addr + index] = data[ST + index];
+ }
+ CP = CP + 1;
+ break;
+ case CALL:
+ addr = d + content(r);
+ if (addr >= Machine.PB) {
+ callPrimitive(addr - Machine.PB);
+ CP = CP + 1;
+ } else {
+ checkSpace(3);
+ if (0 <= n && n <= 15) {
+ data[ST] = content(n); // static link
+ } else {
+ status = failedInvalidInstruction;
+ }
+ data[ST + 1] = LB; // dynamic link
+ data[ST + 2] = CP + 1; // return address
+ LB = ST;
+ ST = ST + 3;
+ CP = addr;
+ }
+ break;
+ case CALLI:
+ ST = ST - 2;
+ addr = data[ST + 1];
+ if (addr >= Machine.PB) {
+ callPrimitive(addr - Machine.PB);
+ CP = CP + 1;
+ } else {
+ // data[ST] = static link already
+ data[ST + 1] = LB; // dynamic link
+ data[ST + 2] = CP + 1; // return address
+ LB = ST;
+ ST = ST + 3;
+ CP = addr;
+ }
+ break;
+ case RETURN:
+ addr = LB - d;
+ CP = data[LB + 2];
+ LB = data[LB + 1];
+ ST = ST - n;
+ for (var index = 0; index < n; index++) {
+ data[addr + index] = data[ST + index];
+ }
+ ST = addr + n;
+ break;
+ case PUSH:
+ checkSpace(d);
+ ST = ST + d;
+ CP = CP + 1;
+ break;
+ case POP:
+ addr = ST - n - d;
+ ST = ST - n;
+ for (var index = 0; index < n; index++) {
+ data[addr + index] = data[ST + index];
+ }
+ ST = addr + n;
+ CP = CP + 1;
+ break;
+ case JUMP:
+ CP = d + content(r);
+ break;
+ case JUMPI:
+ ST = ST - 1;
+ CP = data[ST];
+ break;
+ case JUMPIF:
+ ST = ST - 1;
+ if (data[ST] == n) {
+ CP = d + content(r);
+ } else {
+ CP = CP + 1;
+ }
+ break;
+ case HALT:
+ status = halted;
+ break;
+ }
+ if (CP < CB || CP >= CT) {
+ status = failedInvalidCodeAddress;
+ }
+ } while (status == running);
+ }
+
+ // LOADING
+
+ static void loadObjectProgram(String objectName) {
+ // Loads the TAM object program into code store from the named file.
+
+ boolean finished = false;
+
+ try (var objectFile = new FileInputStream(objectName)) {
+ var objectStream = new DataInputStream(objectFile);
+
+ var addr = Machine.CB;
+ while (!finished) {
+ Machine.code[addr] = Instruction.read(objectStream);
+ if (Machine.code[addr] == null) {
+ finished = true;
+ } else {
+ addr = addr + 1;
+ }
+ }
+ CT = addr;
+ } catch (FileNotFoundException s) {
+ CT = CB;
+ System.err.println("Error opening object file: " + s);
+ } catch (IOException s) {
+ CT = CB;
+ System.err.println("Error reading object file: " + s);
+ }
+ }
+
+ // RUNNING
+
+ public static void main(String[] args) {
+ System.out.println("********** TAM Interpreter (Java Version 2.1) **********");
+
+ if (args.length == 1) {
+ objectName = args[0];
+ } else {
+ objectName = "obj.tam";
+ }
+
+ loadObjectProgram(objectName);
+ if (CT != CB) {
+ startTimeNanos = System.nanoTime();
+ interpretProgram();
+ showStatus();
+ }
+ }
+}
diff --git a/Triangle.AbstractMachine/.gitignore b/Triangle.AbstractMachine/.gitignore
new file mode 100644
index 0000000..8c107fe
--- /dev/null
+++ b/Triangle.AbstractMachine/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/.classpath
+/build/
diff --git a/Triangle.AbstractMachine/.project b/Triangle.AbstractMachine/.project
new file mode 100644
index 0000000..42358c2
--- /dev/null
+++ b/Triangle.AbstractMachine/.project
@@ -0,0 +1,23 @@
+
+
+ Triangle.AbstractMachine
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/Triangle.AbstractMachine/build.gradle b/Triangle.AbstractMachine/build.gradle
new file mode 100644
index 0000000..80f98eb
--- /dev/null
+++ b/Triangle.AbstractMachine/build.gradle
@@ -0,0 +1,4 @@
+apply plugin: 'java-library'
+apply plugin: 'eclipse'
+
+sourceCompatibility = 11
\ No newline at end of file
diff --git a/Triangle.AbstractMachine/pom.xml b/Triangle.AbstractMachine/pom.xml
new file mode 100644
index 0000000..c7675fa
--- /dev/null
+++ b/Triangle.AbstractMachine/pom.xml
@@ -0,0 +1,12 @@
+
+ 4.0.0
+ triangle-abstractmachine
+ jar
+
+ triangle.tools
+ triangle-tools
+ 2.1
+ ../
+
+
\ No newline at end of file
diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java
new file mode 100644
index 0000000..7ca85c9
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java
@@ -0,0 +1,67 @@
+/*
+ * @(#)Instruction.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractMachine;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+
+public class Instruction {
+
+ // Java has no type synonyms, so the following representations are
+ // assumed:
+ //
+ // type
+ // OpCode = 0..15; {4 bits unsigned}
+ // Length = 0..255; {8 bits unsigned}
+ // Operand = -32767..+32767; {16 bits signed}
+
+ // Represents TAM instructions.
+ final OpCode opCode;
+ final Register register;
+ final int length;
+ int operand; // Not final to allow for patching jump address
+
+ public Instruction(OpCode opcode, Register register, int length, int operand) {
+ this.opCode = opcode;
+ this.register = register;
+ this.length = length;
+ this.operand = operand;
+ }
+
+ public void setOperand(int operand) {
+ this.operand = operand;
+ }
+
+ public void write(DataOutputStream output) throws IOException {
+ output.writeInt(opCode.ordinal());
+ output.writeInt(register.ordinal());
+ output.writeInt(length);
+ output.writeInt(operand);
+ }
+
+ public static Instruction read(DataInputStream input) throws IOException {
+ try {
+ var opCode = OpCode.values()[input.readInt()];
+ var register = Register.values()[input.readInt()];
+ var length = input.readInt();
+ var operand = input.readInt();
+ return new Instruction(opCode, register, length, operand);
+ } catch (EOFException s) {
+ return null;
+ }
+ }
+}
diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java
new file mode 100644
index 0000000..c857fa5
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java
@@ -0,0 +1,54 @@
+/*
+ * @(#)Machine.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractMachine;
+
+public final class Machine {
+
+ public final static int maxRoutineLevel = 7;
+
+ // WORDS AND ADDRESSES
+
+ // Java has no type synonyms, so the following representations are
+ // assumed:
+ //
+ // type
+ // Word = -32767..+32767; {16 bits signed}
+ // DoubleWord = -2147483648..+2147483647; {32 bits signed}
+ // CodeAddress = 0..+32767; {15 bits unsigned}
+ // DataAddress = 0..+32767; {15 bits unsigned}
+
+ // INSTRUCTIONS
+
+ // CODE STORE
+
+ public static Instruction[] code = new Instruction[1024];
+
+ // CODE STORE REGISTERS
+
+ public final static int CB = 0, PB = 1024, // = upper bound of code array + 1
+ PT = 1052; // = PB + 28
+
+ // REGISTER NUMBERS
+
+ // DATA REPRESENTATION
+
+ public final static int booleanSize = 1, characterSize = 1, integerSize = 1, addressSize = 1,
+ closureSize = 2 * addressSize,
+
+ linkDataSize = 3 * addressSize,
+
+ falseRep = 0, trueRep = 1, maxintRep = 32767;
+
+}
diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java
new file mode 100644
index 0000000..23ca257
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java
@@ -0,0 +1,5 @@
+package triangle.abstractMachine;
+
+public enum OpCode {
+ LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, CALLI, RETURN, NOP, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT
+}
diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java
new file mode 100644
index 0000000..11bb5bc
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java
@@ -0,0 +1,6 @@
+package triangle.abstractMachine;
+
+public enum Primitive {
+ ID, NOT, AND, OR, SUCC, PRED, NEG, ADD, SUB, MULT, DIV, MOD, LT, LE, GE, GT, EQ, NE, EOL, EOF, GET, PUT, GETEOL,
+ PUTEOL, GETINT, PUTINT, NEW, DISPOSE
+}
diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java
new file mode 100644
index 0000000..0b36262
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java
@@ -0,0 +1,5 @@
+package triangle.abstractMachine;
+
+public enum Register {
+ CB, CT, PB, PT, SB, ST, HB, HT, LB, L1, L2, L3, L4, L5, L6, CP
+}
diff --git a/Triangle.Compiler/.gitignore b/Triangle.Compiler/.gitignore
new file mode 100644
index 0000000..55f062a
--- /dev/null
+++ b/Triangle.Compiler/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.classpath
+/.editorconfig
+/build/
diff --git a/Triangle.Compiler/.project b/Triangle.Compiler/.project
new file mode 100644
index 0000000..dca5b8c
--- /dev/null
+++ b/Triangle.Compiler/.project
@@ -0,0 +1,23 @@
+
+
+ Triangle.Compiler
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/Triangle.Compiler/build.gradle b/Triangle.Compiler/build.gradle
new file mode 100644
index 0000000..9733b3f
--- /dev/null
+++ b/Triangle.Compiler/build.gradle
@@ -0,0 +1,21 @@
+apply plugin: 'java'
+apply plugin: 'application'
+
+sourceCompatibility = 11
+
+repositories {
+ mavenCentral()
+}
+
+
+dependencies {
+ implementation project(':Triangle.AbstractMachine')
+ testImplementation group: 'junit', name: 'junit', version: '4.13.2'
+}
+
+application {
+ mainClass = 'Triangle.Compiler'
+}
+
+// allow access to programs for unit tests
+sourceSets.test.resources.srcDir file("$rootDir/programs")
\ No newline at end of file
diff --git a/Triangle.Compiler/pom.xml b/Triangle.Compiler/pom.xml
new file mode 100644
index 0000000..17b97da
--- /dev/null
+++ b/Triangle.Compiler/pom.xml
@@ -0,0 +1,18 @@
+
+ 4.0.0
+ triangle-compiler
+
+ triangle.tools
+ triangle-tools
+ 2.1
+ ../
+
+
+
+ triangle.tools
+ triangle-abstractmachine
+ 2.1
+
+
+
diff --git a/Triangle.Compiler/src/main/java/triangle/Compiler.java b/Triangle.Compiler/src/main/java/triangle/Compiler.java
new file mode 100644
index 0000000..1a49778
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/Compiler.java
@@ -0,0 +1,152 @@
+/*
+ * @(#)Compiler.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle;
+
+import triangle.abstractSyntaxTrees.Program;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Encoder;
+import triangle.contextualAnalyzer.Checker;
+import triangle.optimiser.ConstantFolder;
+import triangle.syntacticAnalyzer.Parser;
+import triangle.syntacticAnalyzer.Scanner;
+import triangle.syntacticAnalyzer.SourceFile;
+import triangle.treeDrawer.Drawer;
+
+/**
+ * The main driver class for the Triangle compiler.
+ *
+ * @version 2.1 7 Oct 2003
+ * @author Deryck F. Brown
+ */
+public class Compiler {
+
+ /** The filename for the object program, normally obj.tam. */
+ static String objectName = "obj.tam";
+
+ static boolean showTree = false;
+ static boolean folding = false;
+
+ private static Scanner scanner;
+ private static Parser parser;
+ private static Checker checker;
+ private static Encoder encoder;
+ private static Emitter emitter;
+ private static ErrorReporter reporter;
+ private static Drawer drawer;
+
+ /** The AST representing the source program. */
+ private static Program theAST;
+
+ /**
+ * Compile the source program to TAM machine code.
+ *
+ * @param sourceName the name of the file containing the source program.
+ * @param objectName the name of the file containing the object program.
+ * @param showingAST true iff the AST is to be displayed after contextual
+ * analysis
+ * @param showingTable true iff the object description details are to be
+ * displayed during code generation (not currently
+ * implemented).
+ * @return true iff the source program is free of compile-time errors, otherwise
+ * false.
+ */
+ static boolean compileProgram(String sourceName, String objectName, boolean showingAST, boolean showingTable) {
+
+ System.out.println("********** " + "Triangle Compiler (Java Version 2.1)" + " **********");
+
+ System.out.println("Syntactic Analysis ...");
+ SourceFile source = SourceFile.ofPath(sourceName);
+
+ if (source == null) {
+ System.out.println("Can't access source file " + sourceName);
+ System.exit(1);
+ }
+
+ scanner = new Scanner(source);
+ reporter = new ErrorReporter(false);
+ parser = new Parser(scanner, reporter);
+ checker = new Checker(reporter);
+ emitter = new Emitter(reporter);
+ encoder = new Encoder(emitter, reporter);
+ drawer = new Drawer();
+
+ // scanner.enableDebugging();
+ theAST = parser.parseProgram(); // 1st pass
+ if (reporter.getNumErrors() == 0) {
+ // if (showingAST) {
+ // drawer.draw(theAST);
+ // }
+ System.out.println("Contextual Analysis ...");
+ checker.check(theAST); // 2nd pass
+ if (showingAST) {
+ drawer.draw(theAST);
+ }
+ if (folding) {
+ theAST.visit(new ConstantFolder());
+ }
+
+ if (reporter.getNumErrors() == 0) {
+ System.out.println("Code Generation ...");
+ encoder.encodeRun(theAST, showingTable); // 3rd pass
+ }
+ }
+
+ boolean successful = (reporter.getNumErrors() == 0);
+ if (successful) {
+ emitter.saveObjectProgram(objectName);
+ System.out.println("Compilation was successful.");
+ } else {
+ System.out.println("Compilation was unsuccessful.");
+ }
+ return successful;
+ }
+
+ /**
+ * Triangle compiler main program.
+ *
+ * @param args the only command-line argument to the program specifies the
+ * source filename.
+ */
+ public static void main(String[] args) {
+
+ if (args.length < 1) {
+ System.out.println("Usage: tc filename [-o=outputfilename] [tree] [folding]");
+ System.exit(1);
+ }
+
+ parseArgs(args);
+
+ String sourceName = args[0];
+
+ var compiledOK = compileProgram(sourceName, objectName, showTree, false);
+
+ if (!showTree) {
+ System.exit(compiledOK ? 0 : 1);
+ }
+ }
+
+ private static void parseArgs(String[] args) {
+ for (String s : args) {
+ var sl = s.toLowerCase();
+ if (sl.equals("tree")) {
+ showTree = true;
+ } else if (sl.startsWith("-o=")) {
+ objectName = s.substring(3);
+ } else if (sl.equals("folding")) {
+ folding = true;
+ }
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java b/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java
new file mode 100644
index 0000000..cfcc753
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java
@@ -0,0 +1,61 @@
+/*
+ * @(#)ErrorReporter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle;
+
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ErrorReporter {
+
+ private int numErrors;
+
+ private boolean throwExceptions;
+
+ /**
+ * @param throwExceptions if true, throw exceptions (good for unit tests) otherwise write to stdout
+ */
+ public ErrorReporter(boolean throwExceptions) {
+ numErrors = 0;
+ this.throwExceptions = throwExceptions;
+ }
+
+ public void reportError(String message, String tokenName, SourcePosition pos) {
+
+ numErrors++;
+
+ String s = ("ERROR: ");
+
+ for (int p = 0; p < message.length(); p++)
+ if (message.charAt(p) == '%')
+ s += tokenName;
+ else
+ s += message.charAt(p);
+ s += (" " + pos.start + ".." + pos.finish);
+
+ if (throwExceptions) {
+ throw new RuntimeException(s);
+ } else {
+ System.out.println(s);
+ }
+
+ }
+
+ public void reportRestriction(String message) {
+ System.out.println("RESTRICTION: " + message);
+ }
+
+ public int getNumErrors() {
+ return numErrors;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java b/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java
new file mode 100644
index 0000000..90507d0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java
@@ -0,0 +1,46 @@
+/*
+ * @(#)StdEnvironment.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle;
+
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+
+public final class StdEnvironment {
+
+ // These are small ASTs representing standard types.
+
+ public static TypeDenoter booleanType, charType, integerType, anyType, errorType;
+
+ public static TypeDeclaration booleanDecl, charDecl, integerDecl;
+
+ // These are small ASTs representing "declarations" of standard entities.
+
+ public static ConstDeclaration falseDecl, trueDecl, maxintDecl;
+
+ public static UnaryOperatorDeclaration notDecl;
+
+ public static BinaryOperatorDeclaration andDecl, orDecl, addDecl, subtractDecl, multiplyDecl, divideDecl,
+ moduloDecl, equalDecl, unequalDecl, lessDecl, notlessDecl, greaterDecl, notgreaterDecl;
+
+ public static ProcDeclaration getDecl, putDecl, getintDecl, putintDecl, geteolDecl, puteolDecl;
+
+ public static FuncDeclaration chrDecl, ordDecl, eolDecl, eofDecl;
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java
new file mode 100644
index 0000000..669f768
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java
@@ -0,0 +1,34 @@
+/*
+ * @(#)AST.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees;
+
+import triangle.codeGenerator.entities.RuntimeEntity;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class AbstractSyntaxTree {
+
+ private final SourcePosition position;
+
+ public AbstractSyntaxTree(SourcePosition position) {
+ this.position = position;
+ entity = null;
+ }
+
+ public SourcePosition getPosition() {
+ return position;
+ }
+
+ public RuntimeEntity entity;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java
new file mode 100644
index 0000000..17a0aa8
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)Program.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees;
+
+import triangle.abstractSyntaxTrees.commands.Command;
+import triangle.abstractSyntaxTrees.visitors.ProgramVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class Program extends AbstractSyntaxTree {
+
+ public Program(Command cAST, SourcePosition position) {
+ super(position);
+ C = cAST;
+ }
+
+ public Command C;
+
+ public TResult visit(ProgramVisitor visitor, TArg arg) {
+ return visitor.visitProgram(this, arg);
+ }
+
+ public TResult visit(ProgramVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java
new file mode 100644
index 0000000..73188df
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java
@@ -0,0 +1,32 @@
+/*
+ * @(#)ActualParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class ActualParameter extends AbstractSyntaxTree {
+
+ public ActualParameter(SourcePosition position) {
+ super(position);
+ }
+
+ public abstract TResult visit(ActualParameterVisitor visitor, TArg arg);
+
+ public TResult visit(ActualParameterVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java
new file mode 100644
index 0000000..d5a2c9a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java
@@ -0,0 +1,32 @@
+/*
+ * @(#)ActualParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class ActualParameterSequence extends AbstractSyntaxTree {
+
+ public ActualParameterSequence(SourcePosition position) {
+ super(position);
+ }
+
+ public abstract TResult visit(ActualParameterSequenceVisitor v, TArg arg);
+
+ public TResult visit(ActualParameterSequenceVisitor v) {
+ return visit(v, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java
new file mode 100644
index 0000000..ad469dc
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)ConstActualParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ConstActualParameter extends ActualParameter {
+
+ public ConstActualParameter(Expression eAST, SourcePosition position) {
+ super(position);
+ E = eAST;
+ }
+
+ public TResult visit(ActualParameterVisitor v, TArg arg) {
+ return v.visitConstActualParameter(this, arg);
+ }
+
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java
new file mode 100644
index 0000000..13fa735
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)EmptyActualParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class EmptyActualParameterSequence extends ActualParameterSequence {
+
+ public EmptyActualParameterSequence(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(ActualParameterSequenceVisitor v, TArg arg) {
+ return v.visitEmptyActualParameterSequence(this, arg);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java
new file mode 100644
index 0000000..3aa0430
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)FuncActualParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class FuncActualParameter extends ActualParameter {
+
+ public FuncActualParameter(Identifier iAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ }
+
+ public TResult visit(ActualParameterVisitor v, TArg arg) {
+ return v.visitFuncActualParameter(this, arg);
+ }
+
+ public final Identifier I;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java
new file mode 100644
index 0000000..91e53ef
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)MultipleActualParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class MultipleActualParameterSequence extends ActualParameterSequence {
+
+ public MultipleActualParameterSequence(ActualParameter apAST, ActualParameterSequence apsAST,
+ SourcePosition position) {
+ super(position);
+ AP = apAST;
+ APS = apsAST;
+ }
+
+ public TResult visit(ActualParameterSequenceVisitor v, TArg arg) {
+ return v.visitMultipleActualParameterSequence(this, arg);
+ }
+
+ public final ActualParameter AP;
+ public final ActualParameterSequence APS;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java
new file mode 100644
index 0000000..83c40c7
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)ProcActualParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ProcActualParameter extends ActualParameter {
+
+ public ProcActualParameter(Identifier iAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ }
+
+ public TResult visit(ActualParameterVisitor v, TArg arg) {
+ return v.visitProcActualParameter(this, arg);
+ }
+
+ public final Identifier I;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java
new file mode 100644
index 0000000..4dd3a89
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java
@@ -0,0 +1,32 @@
+/*
+ * @(#)SingleActualParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SingleActualParameterSequence extends ActualParameterSequence {
+
+ public SingleActualParameterSequence(ActualParameter apAST, SourcePosition position) {
+ super(position);
+ AP = apAST;
+ }
+
+ public TResult visit(ActualParameterSequenceVisitor v, TArg arg) {
+ return v.visitSingleActualParameterSequence(this, arg);
+ }
+
+ public final ActualParameter AP;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java
new file mode 100644
index 0000000..979dd15
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)VarActualParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.actuals;
+
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class VarActualParameter extends ActualParameter {
+
+ public VarActualParameter(Vname vAST, SourcePosition position) {
+ super(position);
+ V = vAST;
+ }
+
+ public TResult visit(ActualParameterVisitor v, TArg arg) {
+ return v.visitVarActualParameter(this, arg);
+ }
+
+ public final Vname V;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java
new file mode 100644
index 0000000..e90330b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)ArrayAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class ArrayAggregate extends AbstractSyntaxTree {
+
+ public ArrayAggregate(SourcePosition position) {
+ super(position);
+ elemCount = 0;
+ }
+
+ public int elemCount;
+
+ public abstract TResult visit(ArrayAggregateVisitor visitor, TArg arg);
+
+ public TResult visit(ArrayAggregateVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java
new file mode 100644
index 0000000..5b616e1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)MultipleArrayAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class MultipleArrayAggregate extends ArrayAggregate {
+
+ public MultipleArrayAggregate(Expression eAST, ArrayAggregate aaAST, SourcePosition position) {
+ super(position);
+ E = eAST;
+ AA = aaAST;
+ }
+
+ public TResult visit(ArrayAggregateVisitor v, TArg arg) {
+ return v.visitMultipleArrayAggregate(this, arg);
+ }
+
+ public Expression E;
+ public final ArrayAggregate AA;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java
new file mode 100644
index 0000000..1715b2e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java
@@ -0,0 +1,38 @@
+/*
+ * @(#)MultipleRecordAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class MultipleRecordAggregate extends RecordAggregate {
+
+ public MultipleRecordAggregate(Identifier iAST, Expression eAST, RecordAggregate raAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ E = eAST;
+ RA = raAST;
+ }
+
+ public TResult visit(RecordAggregateVisitor v, TArg arg) {
+ return v.visitMultipleRecordAggregate(this, arg);
+ }
+
+ public final Identifier I;
+ public Expression E;
+ public final RecordAggregate RA;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java
new file mode 100644
index 0000000..f79bd9c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)RecordAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.types.FieldTypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class RecordAggregate extends AbstractSyntaxTree {
+
+ public RecordAggregate(SourcePosition position) {
+ super(position);
+ type = null;
+ }
+
+ public FieldTypeDenoter type;
+
+ public abstract TResult visit(RecordAggregateVisitor visitor, TArg arg);
+
+ public TResult visit(RecordAggregateVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java
new file mode 100644
index 0000000..4d5c624
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)SingleArrayAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SingleArrayAggregate extends ArrayAggregate {
+
+ public SingleArrayAggregate(Expression eAST, SourcePosition position) {
+ super(position);
+ E = eAST;
+ }
+
+ public TResult visit(ArrayAggregateVisitor v, TArg arg) {
+ return v.visitSingleArrayAggregate(this, arg);
+ }
+
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java
new file mode 100644
index 0000000..14510c9
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)SingleRecordAggregate.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.aggregates;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SingleRecordAggregate extends RecordAggregate {
+
+ public SingleRecordAggregate(Identifier iAST, Expression eAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ E = eAST;
+ }
+
+ public TResult visit(RecordAggregateVisitor v, TArg arg) {
+ return v.visitSingleRecordAggregate(this, arg);
+ }
+
+ public final Identifier I;
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java
new file mode 100644
index 0000000..66906ae
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)AssignCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class AssignCommand extends Command {
+
+ public AssignCommand(Vname vAST, Expression eAST, SourcePosition position) {
+ super(position);
+ V = vAST;
+ E = eAST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitAssignCommand(this, arg);
+ }
+
+ public final Vname V;
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java
new file mode 100644
index 0000000..40da558
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)CallCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class CallCommand extends Command {
+
+ public CallCommand(Identifier iAST, ActualParameterSequence apsAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ APS = apsAST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitCallCommand(this, arg);
+ }
+
+ public final Identifier I;
+ public final ActualParameterSequence APS;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java
new file mode 100644
index 0000000..cd9b94d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java
@@ -0,0 +1,32 @@
+/*
+ * @(#)Command.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class Command extends AbstractSyntaxTree {
+
+ public Command(SourcePosition position) {
+ super(position);
+ }
+
+ public abstract TResult visit(CommandVisitor visitor, TArg arg);
+
+ public TResult visit(CommandVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java
new file mode 100644
index 0000000..df0a2fb
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)EmptyCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class EmptyCommand extends Command {
+
+ public EmptyCommand(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitEmptyCommand(this, arg);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java
new file mode 100644
index 0000000..e57d560
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)IfCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class IfCommand extends Command {
+
+ public IfCommand(Expression eAST, Command c1AST, Command c2AST, SourcePosition position) {
+ super(position);
+ E = eAST;
+ C1 = c1AST;
+ C2 = c2AST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitIfCommand(this, arg);
+ }
+
+ public Expression E;
+ public final Command C1, C2;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java
new file mode 100644
index 0000000..f59cc5c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)LetCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class LetCommand extends Command {
+
+ public LetCommand(Declaration dAST, Command cAST, SourcePosition position) {
+ super(position);
+ D = dAST;
+ C = cAST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitLetCommand(this, arg);
+ }
+
+ public final Declaration D;
+ public final Command C;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java
new file mode 100644
index 0000000..f8f5f21
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)SequentialCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SequentialCommand extends Command {
+
+ public SequentialCommand(Command c1AST, Command c2AST, SourcePosition position) {
+ super(position);
+ C1 = c1AST;
+ C2 = c2AST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitSequentialCommand(this, arg);
+ }
+
+ public final Command C1, C2;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java
new file mode 100644
index 0000000..af21fde
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)WhileCommand.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.commands;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class WhileCommand extends Command {
+
+ public WhileCommand(Expression eAST, Command cAST, SourcePosition position) {
+ super(position);
+ E = eAST;
+ C = cAST;
+ }
+
+ public TResult visit(CommandVisitor v, TArg arg) {
+ return v.visitWhileCommand(this, arg);
+ }
+
+ public Expression E;
+ public final Command C;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java
new file mode 100644
index 0000000..1a1b524
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)BinaryOperatorDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class BinaryOperatorDeclaration extends Declaration {
+
+ public BinaryOperatorDeclaration(Operator oAST, TypeDenoter arg1AST, TypeDenoter arg2AST, TypeDenoter resultAST,
+ SourcePosition position) {
+ super(position);
+ O = oAST;
+ ARG1 = arg1AST;
+ ARG2 = arg2AST;
+ RES = resultAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitBinaryOperatorDeclaration(this, arg);
+ }
+
+ public final Operator O;
+ public final TypeDenoter ARG1, ARG2, RES;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java
new file mode 100644
index 0000000..86bb95a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java
@@ -0,0 +1,42 @@
+/*
+ * @(#)ConstDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ConstDeclaration extends Declaration implements ConstantDeclaration {
+
+ public ConstDeclaration(Identifier iAST, Expression eAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ E = eAST;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return E.type;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitConstDeclaration(this, arg);
+ }
+
+ public final Identifier I;
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java
new file mode 100644
index 0000000..5241bfc
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+
+public interface ConstantDeclaration {
+
+ TypeDenoter getType();
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java
new file mode 100644
index 0000000..ba1b97c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)Declaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class Declaration extends AbstractSyntaxTree {
+
+ public Declaration(SourcePosition position) {
+ super(position);
+ duplicated = false;
+ }
+
+ public boolean duplicated;
+
+ public abstract TResult visit(DeclarationVisitor visitor, TArg arg);
+
+ public TResult visit(DeclarationVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java
new file mode 100644
index 0000000..55272bb
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java
@@ -0,0 +1,53 @@
+/*
+ * @(#)FuncDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class FuncDeclaration extends Declaration implements FunctionDeclaration {
+
+ public FuncDeclaration(Identifier iAST, FormalParameterSequence fpsAST, TypeDenoter tAST, Expression eAST,
+ SourcePosition position) {
+ super(position);
+ I = iAST;
+ FPS = fpsAST;
+ T = tAST;
+ E = eAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitFuncDeclaration(this, arg);
+ }
+
+ @Override
+ public FormalParameterSequence getFormals() {
+ return FPS;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return T;
+ }
+
+ public final Identifier I;
+ public final FormalParameterSequence FPS;
+ public TypeDenoter T;
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java
new file mode 100644
index 0000000..425fd7c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java
@@ -0,0 +1,12 @@
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+
+public interface FunctionDeclaration {
+
+ FormalParameterSequence getFormals();
+
+ TypeDenoter getType();
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java
new file mode 100644
index 0000000..ba925af
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)ProcDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.commands.Command;
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ProcDeclaration extends Declaration implements ProcedureDeclaration {
+
+ public ProcDeclaration(Identifier iAST, FormalParameterSequence fpsAST, Command cAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ FPS = fpsAST;
+ C = cAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitProcDeclaration(this, arg);
+ }
+
+ @Override
+ public FormalParameterSequence getFormals() {
+ return FPS;
+ }
+
+ public final Identifier I;
+ public final FormalParameterSequence FPS;
+ public final Command C;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java
new file mode 100644
index 0000000..94dee6f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+
+public interface ProcedureDeclaration {
+
+ FormalParameterSequence getFormals();
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java
new file mode 100644
index 0000000..44e6746
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)SequentialDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SequentialDeclaration extends Declaration {
+
+ public SequentialDeclaration(Declaration d1AST, Declaration d2AST, SourcePosition position) {
+ super(position);
+ D1 = d1AST;
+ D2 = d2AST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitSequentialDeclaration(this, arg);
+ }
+
+ public final Declaration D1, D2;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java
new file mode 100644
index 0000000..fd751c6
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)UnaryOperatorDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class UnaryOperatorDeclaration extends Declaration {
+
+ public UnaryOperatorDeclaration(Operator oAST, TypeDenoter argAST, TypeDenoter resultAST, SourcePosition position) {
+ super(position);
+ O = oAST;
+ ARG = argAST;
+ RES = resultAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitUnaryOperatorDeclaration(this, arg);
+ }
+
+ public final Operator O;
+ public final TypeDenoter ARG, RES;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java
new file mode 100644
index 0000000..0933c5f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)VarDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class VarDeclaration extends Declaration implements VariableDeclaration {
+
+ public VarDeclaration(Identifier iAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return T;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitVarDeclaration(this, arg);
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java
new file mode 100644
index 0000000..4c4bfd4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.declarations;
+
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+
+public interface VariableDeclaration {
+
+ TypeDenoter getType();
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java
new file mode 100644
index 0000000..4fe4325
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)ArrayExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.aggregates.ArrayAggregate;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ArrayExpression extends Expression {
+
+ public ArrayExpression(ArrayAggregate aaAST, SourcePosition position) {
+ super(position);
+ AA = aaAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitArrayExpression(this, arg);
+ }
+
+ public final ArrayAggregate AA;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java
new file mode 100644
index 0000000..f5a992a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)BinaryExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class BinaryExpression extends Expression {
+
+ public BinaryExpression(Expression e1AST, Operator oAST, Expression e2AST, SourcePosition position) {
+ super(position);
+ O = oAST;
+ E1 = e1AST;
+ E2 = e2AST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitBinaryExpression(this, arg);
+ }
+
+ public Expression E1;
+ public Expression E2;
+ public final Operator O;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java
new file mode 100644
index 0000000..2eeeb66
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)CallExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class CallExpression extends Expression {
+
+ public CallExpression(Identifier iAST, ActualParameterSequence apsAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ APS = apsAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitCallExpression(this, arg);
+ }
+
+ public final Identifier I;
+ public final ActualParameterSequence APS;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java
new file mode 100644
index 0000000..ba2e959
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)CharacterExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class CharacterExpression extends Expression {
+
+ public CharacterExpression(CharacterLiteral clAST, SourcePosition position) {
+ super(position);
+ CL = clAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitCharacterExpression(this, arg);
+ }
+
+ public final CharacterLiteral CL;
+
+ @Override
+ public boolean isLiteral() {
+ return true;
+ }
+
+ @Override
+ public int getValue() {
+ return CL.getValue();
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java
new file mode 100644
index 0000000..e1fb097
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)EmptyExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class EmptyExpression extends Expression {
+
+ public EmptyExpression(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitEmptyExpression(this, arg);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java
new file mode 100644
index 0000000..70739bd
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)Expression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class Expression extends AbstractSyntaxTree {
+
+ public Expression(SourcePosition position) {
+ super(position);
+ type = null;
+ }
+
+ public TypeDenoter type;
+
+ public boolean isLiteral() {
+ return false;
+ }
+
+ public int getValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ public abstract TResult visit(ExpressionVisitor visitor, TArg arg);
+
+ public TResult visit(ExpressionVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java
new file mode 100644
index 0000000..0bd208d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)IfExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class IfExpression extends Expression {
+
+ public IfExpression(Expression e1AST, Expression e2AST, Expression e3AST, SourcePosition position) {
+ super(position);
+ E1 = e1AST;
+ E2 = e2AST;
+ E3 = e3AST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitIfExpression(this, arg);
+ }
+
+ public Expression E1;
+ public Expression E2;
+ public Expression E3;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java
new file mode 100644
index 0000000..97de244
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)IntegerExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class IntegerExpression extends Expression {
+
+ public IntegerExpression(IntegerLiteral ilAST, SourcePosition position) {
+ super(position);
+ IL = ilAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitIntegerExpression(this, arg);
+ }
+
+ public final IntegerLiteral IL;
+
+ @Override
+ public boolean isLiteral() {
+ return true;
+ }
+
+ @Override
+ public int getValue() {
+ return IL.getValue();
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java
new file mode 100644
index 0000000..1bfef81
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)LetExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class LetExpression extends Expression {
+
+ public LetExpression(Declaration dAST, Expression eAST, SourcePosition position) {
+ super(position);
+ D = dAST;
+ E = eAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitLetExpression(this, arg);
+ }
+
+ public final Declaration D;
+ public Expression E;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java
new file mode 100644
index 0000000..ebe59e2
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)RecordExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.aggregates.RecordAggregate;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class RecordExpression extends Expression {
+
+ public RecordExpression(RecordAggregate raAST, SourcePosition position) {
+ super(position);
+ RA = raAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitRecordExpression(this, arg);
+ }
+
+ public final RecordAggregate RA;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java
new file mode 100644
index 0000000..22199b9
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)UnaryExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class UnaryExpression extends Expression {
+
+ public UnaryExpression(Operator oAST, Expression eAST, SourcePosition position) {
+ super(position);
+ O = oAST;
+ E = eAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitUnaryExpression(this, arg);
+ }
+
+ public Expression E;
+ public final Operator O;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java
new file mode 100644
index 0000000..3bf845a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)VnameExpression.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.expressions;
+
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class VnameExpression extends Expression {
+
+ public VnameExpression(Vname vAST, SourcePosition position) {
+ super(position);
+ V = vAST;
+ }
+
+ public TResult visit(ExpressionVisitor v, TArg arg) {
+ return v.visitVnameExpression(this, arg);
+ }
+
+ public final Vname V;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java
new file mode 100644
index 0000000..c860a53
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java
@@ -0,0 +1,51 @@
+/*
+ * @(#)ConstFormalParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.declarations.ConstantDeclaration;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ConstFormalParameter extends FormalParameter implements ConstantDeclaration {
+
+ public ConstFormalParameter(Identifier iAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return T;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitConstFormalParameter(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object fpAST) {
+ if (fpAST instanceof ConstFormalParameter) {
+ return T.equals(((ConstFormalParameter)fpAST).T);
+ } else {
+ return false;
+ }
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java
new file mode 100644
index 0000000..c478e7f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java
@@ -0,0 +1,34 @@
+/*
+ * @(#)EmptyFormalParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class EmptyFormalParameterSequence extends FormalParameterSequence {
+
+ public EmptyFormalParameterSequence(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(FormalParameterSequenceVisitor v, TArg arg) {
+ return v.visitEmptyFormalParameterSequence(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object fpsAST) {
+ return (fpsAST instanceof EmptyFormalParameterSequence);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java
new file mode 100644
index 0000000..b6b643b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)FormalParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class FormalParameter extends Declaration {
+
+ public FormalParameter(SourcePosition position) {
+ super(position);
+ }
+
+ @Override
+ public abstract boolean equals(Object fpAST);
+
+ public abstract TResult visit(DeclarationVisitor visitor, TArg arg);
+
+ public TResult visit(DeclarationVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java
new file mode 100644
index 0000000..c9941d9
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)FormalParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class FormalParameterSequence extends AbstractSyntaxTree {
+
+ public FormalParameterSequence(SourcePosition position) {
+ super(position);
+ }
+
+ @Override
+ public abstract boolean equals(Object fpsAST);
+
+ public abstract TResult visit(FormalParameterSequenceVisitor visitor, TArg arg);
+
+ public TResult visit(FormalParameterSequenceVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java
new file mode 100644
index 0000000..f362f25
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java
@@ -0,0 +1,59 @@
+/*
+ * @(#)FuncFormalParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.declarations.FunctionDeclaration;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class FuncFormalParameter extends FormalParameter implements FunctionDeclaration {
+
+ public FuncFormalParameter(Identifier iAST, FormalParameterSequence fpsAST, TypeDenoter tAST,
+ SourcePosition position) {
+ super(position);
+ I = iAST;
+ FPS = fpsAST;
+ T = tAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitFuncFormalParameter(this, arg);
+ }
+
+ @Override
+ public FormalParameterSequence getFormals() {
+ return FPS;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return T;
+ }
+
+ @Override
+ public boolean equals(Object fpAST) {
+ if (fpAST instanceof FuncFormalParameter) {
+ FuncFormalParameter ffpAST = (FuncFormalParameter) fpAST;
+ return FPS.equals(ffpAST.FPS) && T.equals(ffpAST.T);
+ } else
+ return false;
+ }
+
+ public final Identifier I;
+ public final FormalParameterSequence FPS;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java
new file mode 100644
index 0000000..32b76fa
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java
@@ -0,0 +1,45 @@
+/*
+ * @(#)MultipleFormalParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class MultipleFormalParameterSequence extends FormalParameterSequence {
+
+ public MultipleFormalParameterSequence(FormalParameter fpAST, FormalParameterSequence fpsAST,
+ SourcePosition position) {
+ super(position);
+ FP = fpAST;
+ FPS = fpsAST;
+ }
+
+ public TResult visit(FormalParameterSequenceVisitor v, TArg arg) {
+ return v.visitMultipleFormalParameterSequence(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object fpsAST) {
+ if (fpsAST instanceof MultipleFormalParameterSequence) {
+ MultipleFormalParameterSequence mfpsAST = (MultipleFormalParameterSequence) fpsAST;
+ return FP.equals(mfpsAST.FP) && FPS.equals(mfpsAST.FPS);
+ } else {
+ return false;
+ }
+ }
+
+ public final FormalParameter FP;
+ public final FormalParameterSequence FPS;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java
new file mode 100644
index 0000000..e89561c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java
@@ -0,0 +1,51 @@
+/*
+ * @(#)ProcFormalParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.declarations.ProcedureDeclaration;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ProcFormalParameter extends FormalParameter implements ProcedureDeclaration {
+
+ public ProcFormalParameter(Identifier iAST, FormalParameterSequence fpsAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ FPS = fpsAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitProcFormalParameter(this, arg);
+ }
+
+ @Override
+ public FormalParameterSequence getFormals() {
+ return FPS;
+ }
+
+ @Override
+ public boolean equals(Object fpAST) {
+ if (fpAST instanceof ProcFormalParameter) {
+ ProcFormalParameter pfpAST = (ProcFormalParameter) fpAST;
+ return FPS.equals(pfpAST.FPS);
+ } else {
+ return false;
+ }
+ }
+
+ public final Identifier I;
+ public final FormalParameterSequence FPS;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java
new file mode 100644
index 0000000..d0f1152
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java
@@ -0,0 +1,42 @@
+/*
+ * @(#)SingleFormalParameterSequence.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SingleFormalParameterSequence extends FormalParameterSequence {
+
+ public SingleFormalParameterSequence(FormalParameter fpAST, SourcePosition position) {
+ super(position);
+ FP = fpAST;
+ }
+
+ public TResult visit(FormalParameterSequenceVisitor v, TArg arg) {
+ return v.visitSingleFormalParameterSequence(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object fpsAST) {
+ if (fpsAST instanceof SingleFormalParameterSequence) {
+ SingleFormalParameterSequence sfpsAST = (SingleFormalParameterSequence) fpsAST;
+ return FP.equals(sfpsAST.FP);
+ } else {
+ return false;
+ }
+ }
+
+ public final FormalParameter FP;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java
new file mode 100644
index 0000000..19efd56
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java
@@ -0,0 +1,51 @@
+/*
+ * @(#)ValFormalParameter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.formals;
+
+import triangle.abstractSyntaxTrees.declarations.VariableDeclaration;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class VarFormalParameter extends FormalParameter implements VariableDeclaration {
+
+ public VarFormalParameter(Identifier iAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ }
+
+ @Override
+ public TypeDenoter getType() {
+ return T;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitVarFormalParameter(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object fpAST) {
+ if (fpAST instanceof VarFormalParameter) {
+ return T.equals(((VarFormalParameter)fpAST).T);
+ } else {
+ return false;
+ }
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java
new file mode 100644
index 0000000..994b8e9
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)CharacterLiteral.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.terminals;
+
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class CharacterLiteral extends Terminal {
+
+ public CharacterLiteral(String spelling, SourcePosition position) {
+ super(spelling, position);
+ }
+
+ public TResult visit(LiteralVisitor v, TArg arg) {
+ return v.visitCharacterLiteral(this, arg);
+ }
+
+ public TResult visit(LiteralVisitor visitor) {
+ return visit(visitor, null);
+ }
+
+ public int getValue() {
+ return spelling.charAt(1);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java
new file mode 100644
index 0000000..139b2c6
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)Identifier.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.terminals;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class Identifier extends Terminal {
+
+ public Identifier(String spelling, SourcePosition position) {
+ super(spelling, position);
+ type = null;
+ decl = null;
+ }
+
+ public TypeDenoter type;
+ public AbstractSyntaxTree decl; // Either a Declaration or a FieldTypeDenoter
+
+ public TResult visit(IdentifierVisitor visitor, TArg arg) {
+ return visitor.visitIdentifier(this, arg);
+ }
+
+ public TResult visit(IdentifierVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java
new file mode 100644
index 0000000..03be9dc
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)IntegerLiteral.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.terminals;
+
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class IntegerLiteral extends Terminal {
+
+ public IntegerLiteral(String spelling, SourcePosition position) {
+ super(spelling, position);
+ }
+
+ public TResult visit(LiteralVisitor v, TArg arg) {
+ return v.visitIntegerLiteral(this, arg);
+ }
+
+ public TResult visit(LiteralVisitor visitor) {
+ return visit(visitor, null);
+ }
+
+ public int getValue() {
+ return Integer.parseInt(spelling);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java
new file mode 100644
index 0000000..f6353d1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)Operator.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.terminals;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.visitors.OperatorVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class Operator extends Terminal {
+
+ public Operator(String spelling, SourcePosition position) {
+ super(spelling, position);
+ decl = null;
+ }
+
+ public Declaration decl;
+
+ public TResult visit(OperatorVisitor v, TArg arg) {
+ return v.visitOperator(this, arg);
+ }
+
+ public TResult visit(OperatorVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java
new file mode 100644
index 0000000..c74ca4b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java
@@ -0,0 +1,28 @@
+/*
+ * @(#)Terminal.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.terminals;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class Terminal extends AbstractSyntaxTree {
+
+ public Terminal(String spelling, SourcePosition position) {
+ super(position);
+ this.spelling = spelling;
+ }
+
+ public final String spelling;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java
new file mode 100644
index 0000000..171c9ca
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)AnyTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class AnyTypeDenoter extends TypeDenoter {
+
+ public AnyTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitAnyTypeDenoter(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return false;
+ }
+
+ @Override
+ public int getSize() {
+ return 0;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java
new file mode 100644
index 0000000..8d43342
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java
@@ -0,0 +1,52 @@
+/*
+ * @(#)ArrayTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ArrayTypeDenoter extends TypeDenoter {
+
+ public ArrayTypeDenoter(IntegerLiteral ilAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ IL = ilAST;
+ T = tAST;
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitArrayTypeDenoter(this, arg);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof ErrorTypeDenoter) {
+ return true;
+ } else if (obj != null && obj instanceof ArrayTypeDenoter) {
+ return this.IL.spelling.compareTo(((ArrayTypeDenoter) obj).IL.spelling) == 0
+ && this.T.equals(((ArrayTypeDenoter) obj).T);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int getSize() {
+ return IL.getValue() * T.getSize();
+ }
+
+ public final IntegerLiteral IL;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java
new file mode 100644
index 0000000..f00e05e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)BoolTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractMachine.Machine;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class BoolTypeDenoter extends TypeDenoter {
+
+ public BoolTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitBoolTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return Machine.booleanSize;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ((obj != null) && (obj instanceof ErrorTypeDenoter)) {
+ return true;
+ } else {
+ return ((obj != null) && (obj instanceof BoolTypeDenoter));
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java
new file mode 100644
index 0000000..7f474b4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)CharTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractMachine.Machine;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class CharTypeDenoter extends TypeDenoter {
+
+ public CharTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitCharTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return Machine.characterSize;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof ErrorTypeDenoter) {
+ return true;
+ } else {
+ return (obj != null && obj instanceof CharTypeDenoter);
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java
new file mode 100644
index 0000000..de6ec0a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)ErrorTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class ErrorTypeDenoter extends TypeDenoter {
+
+ public ErrorTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitErrorTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return true;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java
new file mode 100644
index 0000000..00a2d71
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java
@@ -0,0 +1,24 @@
+/*
+ * @(#)FieldTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class FieldTypeDenoter extends TypeDenoter {
+
+ public FieldTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java
new file mode 100644
index 0000000..9c5fb7f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)IntTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractMachine.Machine;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class IntTypeDenoter extends TypeDenoter {
+
+ public IntTypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitIntTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return Machine.integerSize;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof ErrorTypeDenoter) {
+ return true;
+ } else {
+ return (obj != null && obj instanceof IntTypeDenoter);
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java
new file mode 100644
index 0000000..c9b7658
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java
@@ -0,0 +1,53 @@
+/*
+ * @(#)MultipleFieldTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class MultipleFieldTypeDenoter extends FieldTypeDenoter {
+
+ public MultipleFieldTypeDenoter(Identifier iAST, TypeDenoter tAST, FieldTypeDenoter ftAST,
+ SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ FT = ftAST;
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitMultipleFieldTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return T.getSize() + FT.getSize();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof MultipleFieldTypeDenoter) {
+ MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter) obj;
+ return (this.I.spelling.compareTo(ft.I.spelling) == 0) && this.T.equals(ft.T) && this.FT.equals(ft.FT);
+ } else {
+ return false;
+ }
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+ public FieldTypeDenoter FT;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java
new file mode 100644
index 0000000..8ba90d6
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)RecordTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class RecordTypeDenoter extends TypeDenoter {
+
+ public RecordTypeDenoter(FieldTypeDenoter ftAST, SourcePosition position) {
+ super(position);
+ FT = ftAST;
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitRecordTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return FT.getSize();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof ErrorTypeDenoter) {
+ return true;
+ } else if (obj != null && obj instanceof RecordTypeDenoter) {
+ return this.FT.equals(((RecordTypeDenoter) obj).FT);
+ } else {
+ return false;
+ }
+ }
+
+ public FieldTypeDenoter FT;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java
new file mode 100644
index 0000000..9d2d2b5
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)SimpleTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SimpleTypeDenoter extends TypeDenoter {
+
+ public SimpleTypeDenoter(Identifier iAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitSimpleTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return false; // should not happen
+ }
+
+ public final Identifier I;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java
new file mode 100644
index 0000000..1471bb0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java
@@ -0,0 +1,50 @@
+/*
+ * @(#)SingleFieldTypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SingleFieldTypeDenoter extends FieldTypeDenoter {
+
+ public SingleFieldTypeDenoter(Identifier iAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ }
+
+ public TResult visit(TypeDenoterVisitor v, TArg arg) {
+ return v.visitSingleFieldTypeDenoter(this, arg);
+ }
+
+ @Override
+ public int getSize() {
+ return T.getSize();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof SingleFieldTypeDenoter) {
+ SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter) obj;
+ return (this.I.spelling.compareTo(ft.I.spelling) == 0) && this.T.equals(ft.T);
+ } else {
+ return false;
+ }
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java
new file mode 100644
index 0000000..55e2782
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)TypeDeclaration.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class TypeDeclaration extends Declaration {
+
+ public TypeDeclaration(Identifier iAST, TypeDenoter tAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ T = tAST;
+ }
+
+ public TResult visit(DeclarationVisitor v, TArg arg) {
+ return v.visitTypeDeclaration(this, arg);
+ }
+
+ public final Identifier I;
+ public TypeDenoter T;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java
new file mode 100644
index 0000000..b59be4f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)TypeDenoter.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.types;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class TypeDenoter extends AbstractSyntaxTree {
+
+ public TypeDenoter(SourcePosition position) {
+ super(position);
+ }
+
+ @Override
+ public abstract boolean equals(Object obj);
+
+ public abstract TResult visit(TypeDenoterVisitor visitor, TArg arg);
+
+ public TResult visit(TypeDenoterVisitor visitor) {
+ return visit(visitor, null);
+ }
+
+ public abstract int getSize();
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java
new file mode 100644
index 0000000..66e68a3
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java
@@ -0,0 +1,15 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+
+public interface ActualParameterSequenceVisitor {
+
+ TResult visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, TArg arg);
+
+ TResult visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, TArg arg);
+
+ TResult visitSingleActualParameterSequence(SingleActualParameterSequence ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java
new file mode 100644
index 0000000..9e9630b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java
@@ -0,0 +1,18 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+
+public interface ActualParameterVisitor {
+
+ TResult visitConstActualParameter(ConstActualParameter ast, TArg arg);
+
+ TResult visitFuncActualParameter(FuncActualParameter ast, TArg arg);
+
+ TResult visitProcActualParameter(ProcActualParameter ast, TArg arg);
+
+ TResult visitVarActualParameter(VarActualParameter ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java
new file mode 100644
index 0000000..8d7abec
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java
@@ -0,0 +1,12 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+
+public interface ArrayAggregateVisitor {
+
+ TResult visitMultipleArrayAggregate(MultipleArrayAggregate ast, TArg arg);
+
+ TResult visitSingleArrayAggregate(SingleArrayAggregate ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java
new file mode 100644
index 0000000..336c97d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java
@@ -0,0 +1,27 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+
+public interface CommandVisitor {
+
+ TResult visitAssignCommand(AssignCommand ast, TArg arg);
+
+ TResult visitCallCommand(CallCommand ast, TArg arg);
+
+ TResult visitEmptyCommand(EmptyCommand ast, TArg arg);
+
+ TResult visitIfCommand(IfCommand ast, TArg arg);
+
+ TResult visitLetCommand(LetCommand ast, TArg arg);
+
+ TResult visitSequentialCommand(SequentialCommand ast, TArg arg);
+
+ TResult visitWhileCommand(WhileCommand ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java
new file mode 100644
index 0000000..7ce845d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java
@@ -0,0 +1,30 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+
+public interface DeclarationVisitor extends FormalParameterVisitor {
+
+ TResult visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, TArg arg);
+
+ TResult visitConstDeclaration(ConstDeclaration ast, TArg arg);
+
+ TResult visitFuncDeclaration(FuncDeclaration ast, TArg arg);
+
+ TResult visitProcDeclaration(ProcDeclaration ast, TArg arg);
+
+ TResult visitSequentialDeclaration(SequentialDeclaration ast, TArg arg);
+
+ TResult visitTypeDeclaration(TypeDeclaration ast, TArg arg);
+
+ TResult visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, TArg arg);
+
+ TResult visitVarDeclaration(VarDeclaration ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java
new file mode 100644
index 0000000..ebb76f4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java
@@ -0,0 +1,39 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.EmptyExpression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+
+public interface ExpressionVisitor {
+
+ TResult visitArrayExpression(ArrayExpression ast, TArg arg);
+
+ TResult visitBinaryExpression(BinaryExpression ast, TArg arg);
+
+ TResult visitCallExpression(CallExpression ast, TArg arg);
+
+ TResult visitCharacterExpression(CharacterExpression ast, TArg arg);
+
+ TResult visitEmptyExpression(EmptyExpression ast, TArg arg);
+
+ TResult visitIfExpression(IfExpression ast, TArg arg);
+
+ TResult visitIntegerExpression(IntegerExpression ast, TArg arg);
+
+ TResult visitLetExpression(LetExpression ast, TArg arg);
+
+ TResult visitRecordExpression(RecordExpression ast, TArg arg);
+
+ TResult visitUnaryExpression(UnaryExpression ast, TArg arg);
+
+ TResult visitVnameExpression(VnameExpression ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java
new file mode 100644
index 0000000..2bd3f0d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java
@@ -0,0 +1,12 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+
+public interface FieldTypeDenoterVisitor {
+
+ TResult visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, TArg arg);
+
+ TResult visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java
new file mode 100644
index 0000000..3505451
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java
@@ -0,0 +1,15 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+
+public interface FormalParameterSequenceVisitor {
+
+ TResult visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, TArg arg);
+
+ TResult visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, TArg arg);
+
+ TResult visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java
new file mode 100644
index 0000000..cddb0e7
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java
@@ -0,0 +1,18 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+
+public interface FormalParameterVisitor {
+
+ TResult visitConstFormalParameter(ConstFormalParameter ast, TArg arg);
+
+ TResult visitFuncFormalParameter(FuncFormalParameter ast, TArg arg);
+
+ TResult visitProcFormalParameter(ProcFormalParameter ast, TArg arg);
+
+ TResult visitVarFormalParameter(VarFormalParameter ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java
new file mode 100644
index 0000000..b303b8e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+
+public interface IdentifierVisitor {
+
+ TResult visitIdentifier(Identifier ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java
new file mode 100644
index 0000000..1ca4fa4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java
@@ -0,0 +1,12 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+
+public interface LiteralVisitor {
+
+ TResult visitCharacterLiteral(CharacterLiteral ast, TArg arg);
+
+ TResult visitIntegerLiteral(IntegerLiteral ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java
new file mode 100644
index 0000000..989a653
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.terminals.Operator;
+
+public interface OperatorVisitor {
+
+ TResult visitOperator(Operator ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java
new file mode 100644
index 0000000..aca855c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java
@@ -0,0 +1,9 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.Program;
+
+public interface ProgramVisitor {
+
+ TResult visitProgram(Program ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java
new file mode 100644
index 0000000..20ed097
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java
@@ -0,0 +1,12 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+
+public interface RecordAggregateVisitor {
+
+ TResult visitMultipleRecordAggregate(MultipleRecordAggregate ast, TArg arg);
+
+ TResult visitSingleRecordAggregate(SingleRecordAggregate ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java
new file mode 100644
index 0000000..79b47e3
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java
@@ -0,0 +1,30 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.types.AnyTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.BoolTypeDenoter;
+import triangle.abstractSyntaxTrees.types.CharTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter;
+import triangle.abstractSyntaxTrees.types.IntTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+
+public interface TypeDenoterVisitor extends FieldTypeDenoterVisitor {
+
+ TResult visitAnyTypeDenoter(AnyTypeDenoter ast, TArg arg);
+
+ TResult visitArrayTypeDenoter(ArrayTypeDenoter ast, TArg arg);
+
+ TResult visitBoolTypeDenoter(BoolTypeDenoter ast, TArg arg);
+
+ TResult visitCharTypeDenoter(CharTypeDenoter ast, TArg arg);
+
+ TResult visitErrorTypeDenoter(ErrorTypeDenoter ast, TArg arg);
+
+ TResult visitSimpleTypeDenoter(SimpleTypeDenoter ast, TArg arg);
+
+ TResult visitIntTypeDenoter(IntTypeDenoter ast, TArg arg);
+
+ TResult visitRecordTypeDenoter(RecordTypeDenoter ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java
new file mode 100644
index 0000000..6936a54
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java
@@ -0,0 +1,15 @@
+package triangle.abstractSyntaxTrees.visitors;
+
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+
+public interface VnameVisitor {
+
+ TResult visitDotVname(DotVname ast, TArg arg);
+
+ TResult visitSimpleVname(SimpleVname ast, TArg arg);
+
+ TResult visitSubscriptVname(SubscriptVname ast, TArg arg);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java
new file mode 100644
index 0000000..81c1d41
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)DotVname.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.vnames;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class DotVname extends Vname {
+
+ public DotVname(Vname vAST, Identifier iAST, SourcePosition position) {
+ super(position);
+ V = vAST;
+ I = iAST;
+ }
+
+ public TResult visit(VnameVisitor v, TArg arg) {
+ return v.visitDotVname(this, arg);
+ }
+
+ public final Identifier I;
+ public final Vname V;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java
new file mode 100644
index 0000000..c1ca042
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)SimpleVname.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.vnames;
+
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SimpleVname extends Vname {
+
+ public SimpleVname(Identifier iAST, SourcePosition position) {
+ super(position);
+ I = iAST;
+ }
+
+ public TResult visit(VnameVisitor v, TArg arg) {
+ return v.visitSimpleVname(this, arg);
+ }
+
+ public final Identifier I;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java
new file mode 100644
index 0000000..a95d1f4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)SubscriptVname.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.vnames;
+
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public class SubscriptVname extends Vname {
+
+ public SubscriptVname(Vname vAST, Expression eAST, SourcePosition position) {
+ super(position);
+ V = vAST;
+ E = eAST;
+ }
+
+ public TResult visit(VnameVisitor v, TArg arg) {
+ return v.visitSubscriptVname(this, arg);
+ }
+
+ public Expression E;
+ public final Vname V;
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java
new file mode 100644
index 0000000..633b1f0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)Vname.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.abstractSyntaxTrees.vnames;
+
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public abstract class Vname extends AbstractSyntaxTree {
+
+ public Vname(SourcePosition position) {
+ super(position);
+ variable = false;
+ type = null;
+ }
+
+ public boolean variable, indexed;
+ public int offset;
+ public TypeDenoter type;
+
+ public abstract TResult visit(VnameVisitor visitor, TArg arg);
+
+ public TResult visit(VnameVisitor visitor) {
+ return visit(visitor, null);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java
new file mode 100644
index 0000000..e0b037a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java
@@ -0,0 +1,120 @@
+package triangle.codeGenerator;
+
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import triangle.ErrorReporter;
+import triangle.abstractMachine.Instruction;
+import triangle.abstractMachine.Machine;
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+
+public class Emitter {
+
+ // OBJECT CODE
+
+ // Implementation notes:
+ // Object code is generated directly into the TAM Code Store, starting at
+ // CB.
+ // The address of the next instruction is held in nextInstrAddr.
+
+ ErrorReporter errorReporter;
+
+ int nextInstrAddr;
+
+ public Emitter(ErrorReporter errorReporter) {
+ this.errorReporter = errorReporter;
+ nextInstrAddr = Machine.CB;
+ }
+
+ public int getNextInstrAddr() {
+ return nextInstrAddr;
+ }
+
+ public int emit(OpCode op) {
+ return emit(op, 0, Register.CB, 0);
+ }
+
+ public int emit(OpCode op, int operand) {
+ return emit(op, 0, Register.CB, operand);
+ }
+
+ public int emit(OpCode op, int length, int operand) {
+ return emit(op, length, Register.CB, operand);
+ }
+
+ public int emit(OpCode op, Register staticRegister, Register register, int operand) {
+ return emit(op, staticRegister.ordinal(), register, operand);
+ }
+
+ public int emit(OpCode op, Register register, int operand) {
+ return emit(op, 0, register, operand);
+ }
+
+ public int emit(OpCode op, Register register) {
+ return emit(op, 0, register, 0);
+ }
+
+ public int emit(OpCode op, int length, Register register) {
+ return emit(op, length, register, 0);
+ }
+
+ public int emit(OpCode op, Register register, Primitive primitive) {
+ return emit(op, 0, register, primitive.ordinal());
+ }
+
+ /**
+ * Appends an instruction, with the given fields, to the object code.
+ *
+ * @param op the opcode
+ * @param length the length field
+ * @param register the register field
+ * @param operand the operand field
+ * @return the code address of the new instruction
+ **/
+ public int emit(OpCode op, int length, Register register, int operand) {
+
+ if (length > 255) {
+ errorReporter.reportRestriction("length of operand can't exceed 255 words");
+ length = 255; // to allow code generation to continue
+ }
+
+ var nextInstr = new Instruction(op, register, length, operand);
+
+ var currentInstrAddr = nextInstrAddr;
+ if (nextInstrAddr == Machine.PB) {
+ errorReporter.reportRestriction("too many instructions for code segment");
+ } else {
+ Machine.code[nextInstrAddr++] = nextInstr;
+ }
+ return currentInstrAddr;
+
+ }
+
+ // Patches the d-field of the instruction at address addr with the next
+ // instruction address.
+ public void patch(int addr) {
+ Machine.code[addr].setOperand(nextInstrAddr);
+ }
+
+ /**
+ * Saves the object program in the given object file.
+ *
+ * @param objectFile the object file
+ */
+ public void saveObjectProgram(String objectFileName) {
+ try (var objectFile = new FileOutputStream(objectFileName)) {
+ var objectStream = new DataOutputStream(objectFile);
+ for (var addr = Machine.CB; addr < nextInstrAddr; addr++) {
+ Machine.code[addr].write(objectStream);
+ }
+ } catch (FileNotFoundException fnfe) {
+ System.err.println("Error opening object file: " + fnfe);
+ } catch (IOException ioe) {
+ System.err.println("Error writing object file: " + ioe);
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java
new file mode 100644
index 0000000..2224aa6
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java
@@ -0,0 +1,792 @@
+/*
+ * @(#)Encoder.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator;
+
+import triangle.ErrorReporter;
+import triangle.StdEnvironment;
+import triangle.abstractMachine.Machine;
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.Program;
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.EmptyExpression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.AnyTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.BoolTypeDenoter;
+import triangle.abstractSyntaxTrees.types.CharTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter;
+import triangle.abstractSyntaxTrees.types.IntTypeDenoter;
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor;
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.abstractSyntaxTrees.visitors.OperatorVisitor;
+import triangle.abstractSyntaxTrees.visitors.ProgramVisitor;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.entities.AddressableEntity;
+import triangle.codeGenerator.entities.EqualityRoutine;
+import triangle.codeGenerator.entities.FetchableEntity;
+import triangle.codeGenerator.entities.Field;
+import triangle.codeGenerator.entities.KnownAddress;
+import triangle.codeGenerator.entities.KnownRoutine;
+import triangle.codeGenerator.entities.KnownValue;
+import triangle.codeGenerator.entities.PrimitiveRoutine;
+import triangle.codeGenerator.entities.RoutineEntity;
+import triangle.codeGenerator.entities.RuntimeEntity;
+import triangle.codeGenerator.entities.TypeRepresentation;
+import triangle.codeGenerator.entities.UnknownAddress;
+import triangle.codeGenerator.entities.UnknownRoutine;
+import triangle.codeGenerator.entities.UnknownValue;
+
+public final class Encoder implements ActualParameterVisitor,
+ ActualParameterSequenceVisitor, ArrayAggregateVisitor,
+ CommandVisitor, DeclarationVisitor, ExpressionVisitor,
+ FormalParameterSequenceVisitor, IdentifierVisitor, LiteralVisitor,
+ OperatorVisitor, ProgramVisitor, RecordAggregateVisitor,
+ TypeDenoterVisitor, VnameVisitor {
+
+ // Commands
+ @Override
+ public Void visitAssignCommand(AssignCommand ast, Frame frame) {
+ var valSize = ast.E.visit(this, frame);
+ encodeStore(ast.V, frame.expand(valSize), valSize);
+ return null;
+ }
+
+ @Override
+ public Void visitCallCommand(CallCommand ast, Frame frame) {
+ var argsSize = ast.APS.visit(this, frame);
+ ast.I.visit(this, frame.replace(argsSize));
+ return null;
+ }
+
+ @Override
+ public Void visitEmptyCommand(EmptyCommand ast, Frame frame) {
+ return null;
+ }
+
+ @Override
+ public Void visitIfCommand(IfCommand ast, Frame frame) {
+ ast.E.visit(this, frame);
+ var jumpifAddr = emitter.emit(OpCode.JUMPIF, Machine.falseRep, Register.CB, 0);
+ ast.C1.visit(this, frame);
+ var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0);
+ emitter.patch(jumpifAddr);
+ ast.C2.visit(this, frame);
+ emitter.patch(jumpAddr);
+ return null;
+ }
+
+ @Override
+ public Void visitLetCommand(LetCommand ast, Frame frame) {
+ var extraSize = ast.D.visit(this, frame);
+ ast.C.visit(this, frame.expand(extraSize));
+ if (extraSize > 0) {
+ emitter.emit(OpCode.POP, extraSize);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitSequentialCommand(SequentialCommand ast, Frame frame) {
+ ast.C1.visit(this, frame);
+ ast.C2.visit(this, frame);
+ return null;
+ }
+
+ @Override
+ public Void visitWhileCommand(WhileCommand ast, Frame frame) {
+ var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0);
+ var loopAddr = emitter.getNextInstrAddr();
+ ast.C.visit(this, frame);
+ emitter.patch(jumpAddr);
+ ast.E.visit(this, frame);
+ emitter.emit(OpCode.JUMPIF, Machine.trueRep, Register.CB, loopAddr);
+ return null;
+ }
+
+ // Expressions
+ @Override
+ public Integer visitArrayExpression(ArrayExpression ast, Frame frame) {
+ ast.type.visit(this, frame);
+ return ast.AA.visit(this, frame);
+ }
+
+ @Override
+ public Integer visitBinaryExpression(BinaryExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ var valSize1 = ast.E1.visit(this, frame);
+ var frame1 = frame.expand(valSize1);
+ var valSize2 = ast.E2.visit(this, frame1);
+ var frame2 = frame.replace(valSize1 + valSize2);
+ ast.O.visit(this, frame2);
+ return valSize;
+ }
+
+ @Override
+ public Integer visitCallExpression(CallExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ var argsSize = ast.APS.visit(this, frame);
+ ast.I.visit(this, frame.replace(argsSize));
+ return valSize;
+ }
+
+ @Override
+ public Integer visitCharacterExpression(CharacterExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ emitter.emit(OpCode.LOADL, ast.CL.getValue());
+ return valSize;
+ }
+
+ @Override
+ public Integer visitEmptyExpression(EmptyExpression ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitIfExpression(IfExpression ast, Frame frame) {
+ ast.type.visit(this);
+ ast.E1.visit(this, frame);
+ var jumpifAddr = emitter.emit(OpCode.JUMPIF, Machine.falseRep, Register.CB, 0);
+ var valSize = ast.E2.visit(this, frame);
+ var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0);
+ emitter.patch(jumpifAddr);
+ valSize = ast.E3.visit(this, frame);
+ emitter.patch(jumpAddr);
+ return valSize;
+ }
+
+ @Override
+ public Integer visitIntegerExpression(IntegerExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ emitter.emit(OpCode.LOADL, ast.IL.getValue());
+ return valSize;
+ }
+
+ @Override
+ public Integer visitLetExpression(LetExpression ast, Frame frame) {
+ ast.type.visit(this);
+ var extraSize = ast.D.visit(this, frame);
+ var frame1 = frame.expand(extraSize);
+ var valSize = ast.E.visit(this, frame1);
+ if (extraSize > 0) {
+ emitter.emit(OpCode.POP, valSize, extraSize);
+ }
+ return valSize;
+ }
+
+ @Override
+ public Integer visitRecordExpression(RecordExpression ast, Frame frame) {
+ ast.type.visit(this);
+ return ast.RA.visit(this, frame);
+ }
+
+ @Override
+ public Integer visitUnaryExpression(UnaryExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ ast.E.visit(this, frame);
+ ast.O.visit(this, frame.replace(valSize));
+ return valSize;
+ }
+
+ @Override
+ public Integer visitVnameExpression(VnameExpression ast, Frame frame) {
+ var valSize = ast.type.visit(this);
+ encodeFetch(ast.V, frame, valSize);
+ return valSize;
+ }
+
+ // Declarations
+ @Override
+ public Integer visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitConstDeclaration(ConstDeclaration ast, Frame frame) {
+ var extraSize = 0;
+ if (ast.E.isLiteral()) {
+ ast.entity = new KnownValue(ast.E.type.getSize(), ast.E.getValue());
+ } else {
+ var valSize = ast.E.visit(this, frame);
+ ast.entity = new UnknownValue(valSize, frame);
+ extraSize = valSize;
+ }
+ writeTableDetails(ast);
+ return extraSize;
+ }
+
+ @Override
+ public Integer visitFuncDeclaration(FuncDeclaration ast, Frame frame) {
+ var argsSize = 0;
+ var valSize = 0;
+
+ var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0);
+ ast.entity = new KnownRoutine(Machine.closureSize, frame.getLevel(), emitter.getNextInstrAddr());
+ writeTableDetails(ast);
+ if (frame.getLevel() == Machine.maxRoutineLevel) {
+ reporter.reportRestriction("can't nest routines more than 7 deep");
+ } else {
+ var frame1 = frame.push(0);
+ argsSize = ast.FPS.visit(this, frame1);
+ var frame2 = frame.push(Machine.linkDataSize);
+ valSize = ast.E.visit(this, frame2);
+ }
+ emitter.emit(OpCode.RETURN, valSize, argsSize);
+ emitter.patch(jumpAddr);
+ return 0;
+ }
+
+ @Override
+ public Integer visitProcDeclaration(ProcDeclaration ast, Frame frame) {
+ var argsSize = 0;
+ var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0);
+ ast.entity = new KnownRoutine(Machine.closureSize, frame.getLevel(), emitter.getNextInstrAddr());
+ writeTableDetails(ast);
+ if (frame.getLevel() == Machine.maxRoutineLevel) {
+ reporter.reportRestriction("can't nest routines so deeply");
+ } else {
+ var frame1 = frame.push(0);
+ argsSize = ast.FPS.visit(this, frame1);
+ var frame2 = frame.push(Machine.linkDataSize);
+ ast.C.visit(this, frame2);
+ }
+ emitter.emit(OpCode.RETURN, argsSize);
+ emitter.patch(jumpAddr);
+ return 0;
+ }
+
+ @Override
+ public Integer visitSequentialDeclaration(SequentialDeclaration ast, Frame frame) {
+ var extraSize1 = ast.D1.visit(this, frame);
+ var frame1 = frame.expand(extraSize1);
+ var extraSize2 = ast.D2.visit(this, frame1);
+ return extraSize1 + extraSize2;
+ }
+
+ @Override
+ public Integer visitTypeDeclaration(TypeDeclaration ast, Frame frame) {
+ // just to ensure the type's representation is decided
+ ast.T.visit(this);
+ return 0;
+ }
+
+ @Override
+ public Integer visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitVarDeclaration(VarDeclaration ast, Frame frame) {
+ var extraSize = ast.T.visit(this);
+ emitter.emit(OpCode.PUSH, extraSize);
+ ast.entity = new KnownAddress(Machine.addressSize, frame);
+ writeTableDetails(ast);
+ return extraSize;
+ }
+
+ // Array Aggregates
+ @Override
+ public Integer visitMultipleArrayAggregate(MultipleArrayAggregate ast, Frame frame) {
+ var elemSize = ast.E.visit(this, frame);
+ var frame1 = frame.expand(elemSize);
+ var arraySize = ast.AA.visit(this, frame1);
+ return elemSize + arraySize;
+ }
+
+ @Override
+ public Integer visitSingleArrayAggregate(SingleArrayAggregate ast, Frame frame) {
+ return ast.E.visit(this, frame);
+ }
+
+ // Record Aggregates
+ @Override
+ public Integer visitMultipleRecordAggregate(MultipleRecordAggregate ast, Frame frame) {
+ var fieldSize = ast.E.visit(this, frame);
+ var frame1 = frame.expand(fieldSize);
+ var recordSize = ast.RA.visit(this, frame1);
+ return fieldSize + recordSize;
+ }
+
+ @Override
+ public Integer visitSingleRecordAggregate(SingleRecordAggregate ast, Frame frame) {
+ return ast.E.visit(this, frame);
+ }
+
+ // Formal Parameters
+ @Override
+ public Integer visitConstFormalParameter(ConstFormalParameter ast, Frame frame) {
+ var valSize = ast.T.visit(this);
+ ast.entity = new UnknownValue(valSize, frame.getLevel(), -frame.getSize() - valSize);
+ writeTableDetails(ast);
+ return valSize;
+ }
+
+ @Override
+ public Integer visitFuncFormalParameter(FuncFormalParameter ast, Frame frame) {
+ var argsSize = Machine.closureSize;
+ ast.entity = new UnknownRoutine(Machine.closureSize, frame.getLevel(), -frame.getSize() - argsSize);
+ writeTableDetails(ast);
+ return argsSize;
+ }
+
+ @Override
+ public Integer visitProcFormalParameter(ProcFormalParameter ast, Frame frame) {
+ var argsSize = Machine.closureSize;
+ ast.entity = new UnknownRoutine(Machine.closureSize, frame.getLevel(), -frame.getSize() - argsSize);
+ writeTableDetails(ast);
+ return argsSize;
+ }
+
+ @Override
+ public Integer visitVarFormalParameter(VarFormalParameter ast, Frame frame) {
+ ast.T.visit(this);
+ ast.entity = new UnknownAddress(Machine.addressSize, frame.getLevel(), -frame.getSize() - Machine.addressSize);
+ writeTableDetails(ast);
+ return Machine.addressSize;
+ }
+
+ @Override
+ public Integer visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Frame frame) {
+ var argsSize1 = ast.FPS.visit(this, frame);
+ var frame1 = frame.expand(argsSize1);
+ var argsSize2 = ast.FP.visit(this, frame1);
+ return argsSize1 + argsSize2;
+ }
+
+ @Override
+ public Integer visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Frame frame) {
+ return ast.FP.visit(this, frame);
+ }
+
+ // Actual Parameters
+ @Override
+ public Integer visitConstActualParameter(ConstActualParameter ast, Frame frame) {
+ return ast.E.visit(this, frame);
+ }
+
+ @Override
+ public Integer visitFuncActualParameter(FuncActualParameter ast, Frame frame) {
+ var routineEntity = (RoutineEntity) ast.I.decl.entity;
+ routineEntity.encodeFetch(emitter, frame);
+ return Machine.closureSize;
+ }
+
+ @Override
+ public Integer visitProcActualParameter(ProcActualParameter ast, Frame frame) {
+ var routineEntity = (RoutineEntity) ast.I.decl.entity;
+ routineEntity.encodeFetch(emitter, frame);
+ return Machine.closureSize;
+ }
+
+ @Override
+ public Integer visitVarActualParameter(VarActualParameter ast, Frame frame) {
+ encodeFetchAddress(ast.V, frame);
+ return Machine.addressSize;
+ }
+
+ @Override
+ public Integer visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Frame frame) {
+ var argsSize1 = ast.AP.visit(this, frame);
+ var frame1 = frame.expand(argsSize1);
+ var argsSize2 = ast.APS.visit(this, frame1);
+ return argsSize1 + argsSize2;
+ }
+
+ @Override
+ public Integer visitSingleActualParameterSequence(SingleActualParameterSequence ast, Frame frame) {
+ return ast.AP.visit(this, frame);
+ }
+
+ // Type Denoters
+ @Override
+ public Integer visitAnyTypeDenoter(AnyTypeDenoter ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitArrayTypeDenoter(ArrayTypeDenoter ast, Frame frame) {
+ int typeSize;
+ if (ast.entity == null) {
+ var elemSize = ast.T.visit(this);
+ typeSize = ast.IL.getValue() * elemSize;
+ ast.entity = new TypeRepresentation(typeSize);
+ writeTableDetails(ast);
+ } else {
+ typeSize = ast.entity.getSize();
+ }
+ return typeSize;
+ }
+
+ @Override
+ public Integer visitBoolTypeDenoter(BoolTypeDenoter ast, Frame frame) {
+ if (ast.entity == null) {
+ ast.entity = new TypeRepresentation(Machine.booleanSize);
+ writeTableDetails(ast);
+ }
+ return Machine.booleanSize;
+ }
+
+ @Override
+ public Integer visitCharTypeDenoter(CharTypeDenoter ast, Frame frame) {
+ if (ast.entity == null) {
+ ast.entity = new TypeRepresentation(Machine.characterSize);
+ writeTableDetails(ast);
+ }
+ return Machine.characterSize;
+ }
+
+ @Override
+ public Integer visitErrorTypeDenoter(ErrorTypeDenoter ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitSimpleTypeDenoter(SimpleTypeDenoter ast, Frame frame) {
+ return 0;
+ }
+
+ @Override
+ public Integer visitIntTypeDenoter(IntTypeDenoter ast, Frame frame) {
+ if (ast.entity == null) {
+ ast.entity = new TypeRepresentation(Machine.integerSize);
+ writeTableDetails(ast);
+ }
+ return Machine.integerSize;
+ }
+
+ @Override
+ public Integer visitRecordTypeDenoter(RecordTypeDenoter ast, Frame frame) {
+ int typeSize;
+ if (ast.entity == null) {
+ typeSize = ast.FT.visit(this, frame);
+ ast.entity = new TypeRepresentation(typeSize);
+ writeTableDetails(ast);
+ } else {
+ typeSize = ast.entity.getSize();
+ }
+ return typeSize;
+ }
+
+ @Override
+ public Integer visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Frame frame) {
+ if (frame == null) { // in this case, we're just using the frame to wrap up the size
+ frame = Frame.Initial;
+ }
+
+ var offset = frame.getSize();
+ int fieldSize;
+ if (ast.entity == null) {
+ fieldSize = ast.T.visit(this);
+ ast.entity = new Field(fieldSize, offset);
+ writeTableDetails(ast);
+ } else {
+ fieldSize = ast.entity.getSize();
+ }
+
+ var offset1 = frame.replace(offset + fieldSize);
+ var recSize = ast.FT.visit(this, offset1);
+ return fieldSize + recSize;
+ }
+
+ @Override
+ public Integer visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Frame frame) {
+ var offset = frame.getSize();
+ int fieldSize;
+ if (ast.entity == null) {
+ fieldSize = ast.T.visit(this);
+ ast.entity = new Field(fieldSize, offset);
+ writeTableDetails(ast);
+ } else {
+ fieldSize = ast.entity.getSize();
+ }
+
+ return fieldSize;
+ }
+
+ // Literals, Identifiers and Operators
+ @Override
+ public Void visitCharacterLiteral(CharacterLiteral ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitIdentifier(Identifier ast, Frame frame) {
+ var routineEntity = (RoutineEntity) ast.decl.entity;
+ routineEntity.encodeCall(emitter, frame);
+ return null;
+ }
+
+ @Override
+ public Void visitIntegerLiteral(IntegerLiteral ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitOperator(Operator ast, Frame frame) {
+ var routineEntity = (RoutineEntity) ast.decl.entity;
+ routineEntity.encodeCall(emitter, frame);
+ return null;
+ }
+
+ // Value-or-variable names
+ @Override
+ public RuntimeEntity visitDotVname(DotVname ast, Frame frame) {
+ var baseObject = ast.V.visit(this, frame);
+ ast.offset = ast.V.offset + ((Field) ast.I.decl.entity).getFieldOffset();
+ // I.decl points to the appropriate record field
+ ast.indexed = ast.V.indexed;
+ return baseObject;
+ }
+
+ @Override
+ public RuntimeEntity visitSimpleVname(SimpleVname ast, Frame frame) {
+ ast.offset = 0;
+ ast.indexed = false;
+ return ast.I.decl.entity;
+ }
+
+ @Override
+ public RuntimeEntity visitSubscriptVname(SubscriptVname ast, Frame frame) {
+ var baseObject = ast.V.visit(this, frame);
+ ast.offset = ast.V.offset;
+ ast.indexed = ast.V.indexed;
+ var elemSize = ast.type.visit(this);
+ if (ast.E.isLiteral()) {
+ ast.offset = ast.offset + ast.E.getValue() * elemSize;
+ } else {
+ // v-name is indexed by a proper expression, not a literal
+ if (ast.indexed) {
+ frame = frame.expand(Machine.integerSize);
+ }
+ ast.E.visit(this, frame);
+ if (elemSize != 1) {
+ emitter.emit(OpCode.LOADL, 0, elemSize);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.MULT);
+ }
+ if (ast.indexed)
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ else {
+ ast.indexed = true;
+ }
+ }
+ return baseObject;
+ }
+
+ // Programs
+ @Override
+ public Void visitProgram(Program ast, Frame frame) {
+ return ast.C.visit(this, frame);
+ }
+
+ public Encoder(Emitter emitter, ErrorReporter reporter) {
+ this.emitter = emitter;
+ this.reporter = reporter;
+
+ elaborateStdEnvironment();
+ }
+
+ private Emitter emitter;
+
+ private ErrorReporter reporter;
+
+ // Generates code to run a program.
+ // showingTable is true iff entity description details
+ // are to be displayed.
+ public final void encodeRun(Program program, boolean showingTable) {
+ tableDetailsReqd = showingTable;
+ // startCodeGeneration();
+ program.visit(this, Frame.Initial);
+ emitter.emit(OpCode.HALT);
+ }
+
+ // Decides run-time representation of a standard constant.
+ private final void elaborateStdConst(ConstDeclaration constDeclaration, int value) {
+
+ var typeSize = constDeclaration.E.type.visit(this);
+ constDeclaration.entity = new KnownValue(typeSize, value);
+ writeTableDetails(constDeclaration);
+ }
+
+ // Decides run-time representation of a standard routine.
+ private final void elaborateStdPrimRoutine(Declaration routineDeclaration, Primitive primitive) {
+ routineDeclaration.entity = new PrimitiveRoutine(Machine.closureSize, primitive);
+ writeTableDetails(routineDeclaration);
+ }
+
+ private final void elaborateStdEqRoutine(Declaration routineDeclaration, Primitive primitive) {
+ routineDeclaration.entity = new EqualityRoutine(Machine.closureSize, primitive);
+ writeTableDetails(routineDeclaration);
+ }
+
+ private final void elaborateStdEnvironment() {
+ tableDetailsReqd = false;
+ elaborateStdConst(StdEnvironment.falseDecl, Machine.falseRep);
+ elaborateStdConst(StdEnvironment.trueDecl, Machine.trueRep);
+ elaborateStdPrimRoutine(StdEnvironment.notDecl, Primitive.NOT);
+ elaborateStdPrimRoutine(StdEnvironment.andDecl, Primitive.AND);
+ elaborateStdPrimRoutine(StdEnvironment.orDecl, Primitive.OR);
+ elaborateStdConst(StdEnvironment.maxintDecl, Machine.maxintRep);
+ elaborateStdPrimRoutine(StdEnvironment.addDecl, Primitive.ADD);
+ elaborateStdPrimRoutine(StdEnvironment.subtractDecl, Primitive.SUB);
+ elaborateStdPrimRoutine(StdEnvironment.multiplyDecl, Primitive.MULT);
+ elaborateStdPrimRoutine(StdEnvironment.divideDecl, Primitive.DIV);
+ elaborateStdPrimRoutine(StdEnvironment.moduloDecl, Primitive.MOD);
+ elaborateStdPrimRoutine(StdEnvironment.lessDecl, Primitive.LT);
+ elaborateStdPrimRoutine(StdEnvironment.notgreaterDecl, Primitive.LE);
+ elaborateStdPrimRoutine(StdEnvironment.greaterDecl, Primitive.GT);
+ elaborateStdPrimRoutine(StdEnvironment.notlessDecl, Primitive.GE);
+ elaborateStdPrimRoutine(StdEnvironment.chrDecl, Primitive.ID);
+ elaborateStdPrimRoutine(StdEnvironment.ordDecl, Primitive.ID);
+ elaborateStdPrimRoutine(StdEnvironment.eolDecl, Primitive.EOL);
+ elaborateStdPrimRoutine(StdEnvironment.eofDecl, Primitive.EOF);
+ elaborateStdPrimRoutine(StdEnvironment.getDecl, Primitive.GET);
+ elaborateStdPrimRoutine(StdEnvironment.putDecl, Primitive.PUT);
+ elaborateStdPrimRoutine(StdEnvironment.getintDecl, Primitive.GETINT);
+ elaborateStdPrimRoutine(StdEnvironment.putintDecl, Primitive.PUTINT);
+ elaborateStdPrimRoutine(StdEnvironment.geteolDecl, Primitive.GETEOL);
+ elaborateStdPrimRoutine(StdEnvironment.puteolDecl, Primitive.PUTEOL);
+ elaborateStdEqRoutine(StdEnvironment.equalDecl, Primitive.EQ);
+ elaborateStdEqRoutine(StdEnvironment.unequalDecl, Primitive.NE);
+ }
+
+ boolean tableDetailsReqd;
+
+ public static void writeTableDetails(AbstractSyntaxTree ast) {
+ }
+
+ // Generates code to pop the top off the stack
+ // and store the value in a named constant or variable
+ // frame the local stack frame when
+ // the constant or variable is fetched at run-time.
+ // valSize is the size of the constant or variable's value.
+
+ private void encodeStore(Vname V, Frame frame, int valSize) {
+
+ var baseObject = (AddressableEntity) V.visit(this, frame);
+ // If indexed = true, code will have been generated to load an index value.
+ if (valSize > 255) {
+ reporter.reportRestriction("can't store values larger than 255 words");
+ valSize = 255; // to allow code generation to continue
+ }
+
+ baseObject.encodeStore(emitter, frame, valSize, V);
+ }
+
+ // Generates code to fetch the value of a named constant or variable
+ // and push it on to the stack.
+ // currentLevel is the routine level where the vname occurs.
+ // frameSize is the anticipated size of the local stack frame when
+ // the constant or variable is fetched at run-time.
+ // valSize is the size of the constant or variable's value.
+
+ private void encodeFetch(Vname V, Frame frame, int valSize) {
+
+ var baseObject = (FetchableEntity) V.visit(this, frame);
+ // If indexed = true, code will have been generated to load an index value.
+ if (valSize > 255) {
+ reporter.reportRestriction("can't load values larger than 255 words");
+ valSize = 255; // to allow code generation to continue
+ }
+
+ baseObject.encodeFetch(emitter, frame, valSize, V);
+ }
+
+ // Generates code to compute and push the address of a named variable.
+ // vname is the program phrase that names this variable.
+ // currentLevel is the routine level where the vname occurs.
+ // frameSize is the anticipated size of the local stack frame when
+ // the variable is addressed at run-time.
+
+ private void encodeFetchAddress(Vname V, Frame frame) {
+
+ var baseObject = (AddressableEntity) V.visit(this, frame);
+ baseObject.encodeFetchAddress(emitter, frame, V);
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java
new file mode 100644
index 0000000..5aba4e4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java
@@ -0,0 +1,73 @@
+/*
+ * @(#)Frame.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator;
+
+import triangle.abstractMachine.Register;
+import triangle.codeGenerator.entities.ObjectAddress;
+
+public class Frame {
+
+ public static final Frame Initial = new Frame(0, 0);
+
+ private final int level;
+
+ private final int size;
+
+ private Frame(int level, int size) {
+ this.level = level;
+ this.size = size;
+ }
+
+ public final int getLevel() {
+ return level;
+ }
+
+ public final int getSize() {
+ return size;
+ }
+
+ public Frame expand(int increment) {
+ return new Frame(level, size + increment);
+ }
+
+ public Frame replace(int size) {
+ return new Frame(level, size);
+ }
+
+ public Frame push(int size) {
+ return new Frame(level + 1, size);
+ }
+
+ /**
+ * Returns the display register appropriate for object code at the current
+ * static level to access a data object at the static level of the given
+ * address.
+ *
+ * @param address the address of the data object
+ * @return the display register required for static addressing
+ */
+ public Register getDisplayRegister(ObjectAddress address) {
+ if (address.getLevel() == 0) {
+ return Register.SB;
+ }
+
+ if (level - address.getLevel() <= 6) {
+ return Register.values()[Register.LB.ordinal() + level - address.getLevel()]; // LB|L1|...|L6
+ }
+
+ // _errorReporter.ReportRestriction("can't access data more than 6 levels out");
+ return Register.L6; // to allow code generation to continue
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java
new file mode 100644
index 0000000..3896e32
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java
@@ -0,0 +1,29 @@
+package triangle.codeGenerator.entities;
+
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public abstract class AddressableEntity extends RuntimeEntity implements FetchableEntity {
+
+ protected final ObjectAddress address;
+
+ protected AddressableEntity(int size, int level, int displacement) {
+ super(size);
+ address = new ObjectAddress(level, displacement);
+ }
+
+ protected AddressableEntity(int size, Frame frame) {
+ this(size, frame.getLevel(), frame.getSize());
+ }
+
+ public ObjectAddress getAddress() {
+ return address;
+ }
+
+ public abstract void encodeStore(Emitter emitter, Frame frame, int size, Vname vname);
+
+ public abstract void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname);
+
+ public abstract void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname);
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java
new file mode 100644
index 0000000..6c86baf
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java
@@ -0,0 +1,46 @@
+/*
+ * @(#)EqualityRoutine.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class EqualityRoutine extends RuntimeEntity implements RoutineEntity {
+
+ private final Primitive primitive;
+
+ public EqualityRoutine(int size, Primitive primitive) {
+ super(size);
+ this.primitive = primitive;
+ }
+
+ public final Primitive getPrimitive() {
+ return primitive;
+ }
+
+ public void encodeCall(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOADL, frame.getSize() / 2);
+ emitter.emit(OpCode.CALL, Register.PB, primitive);
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOADA, 0, Register.SB, 0);
+ emitter.emit(OpCode.LOADA, Register.PB, primitive);
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java
new file mode 100644
index 0000000..1e4194c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java
@@ -0,0 +1,11 @@
+package triangle.codeGenerator.entities;
+
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public interface FetchableEntity {
+
+ void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname);
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java
new file mode 100644
index 0000000..2354136
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)Field.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+public class Field extends RuntimeEntity {
+
+ private final int fieldOffset;
+
+ public Field(int size, int fieldOffset) {
+ super(size);
+ this.fieldOffset = fieldOffset;
+ }
+
+ public final int getFieldOffset() {
+ return fieldOffset;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java
new file mode 100644
index 0000000..e62879e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java
@@ -0,0 +1,62 @@
+/*
+ * @(#)KnownAddress.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class KnownAddress extends AddressableEntity {
+
+ public KnownAddress(int size, int level, int displacement) {
+ super(size, level, displacement);
+ }
+
+ public KnownAddress(int size, Frame frame) {
+ super(size, frame);
+ }
+
+ public void encodeStore(Emitter emitter, Frame frame, int size, Vname vname) {
+ if (vname.indexed) {
+ emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ emitter.emit(OpCode.STOREI, size, 0);
+ } else {
+ emitter.emit(OpCode.STORE, size, frame.getDisplayRegister(address),
+ address.getDisplacement() + vname.offset);
+ }
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) {
+ if (vname.indexed) {
+ emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ emitter.emit(OpCode.LOADI, size, 0);
+ } else {
+ emitter.emit(OpCode.LOAD, size, frame.getDisplayRegister(address),
+ address.getDisplacement() + vname.offset);
+ }
+ }
+
+ public void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname) {
+ emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset);
+ if (vname.indexed) {
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java
new file mode 100644
index 0000000..4adca41
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)KnownRoutine.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Register;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class KnownRoutine extends RuntimeEntity implements RoutineEntity {
+
+ private final ObjectAddress address;
+
+ public KnownRoutine(int size, int level, int displacement) {
+ super(size);
+ address = new ObjectAddress(level, displacement);
+ }
+
+ public final ObjectAddress getAddress() {
+ return address;
+ }
+
+ public void encodeCall(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.CALL, frame.getDisplayRegister(address), Register.CB, address.getDisplacement());
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOADA, frame.getDisplayRegister(address), 0);
+ emitter.emit(OpCode.LOADA, Register.CB, address.getDisplacement());
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java
new file mode 100644
index 0000000..af24be5
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)KnownValue.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class KnownValue extends RuntimeEntity implements FetchableEntity {
+
+ private final int value;
+
+ public KnownValue(int size, int value) {
+ super(size);
+ this.value = value;
+ }
+
+ public final int getValue() {
+ return value;
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) {
+ // presumably offset = 0 and indexed = false
+ emitter.emit(OpCode.LOADL, 0, value);
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java
new file mode 100644
index 0000000..7440c68
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)ObjectAddress.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+public class ObjectAddress {
+
+ private final int level;
+
+ private final int displacement;
+
+ public ObjectAddress(int level, int displacement) {
+ this.level = level;
+ this.displacement = displacement;
+ }
+
+ public final int getLevel() {
+ return level;
+ }
+
+ public int getDisplacement() {
+ return displacement;
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java
new file mode 100644
index 0000000..4cf3237
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)PrimitiveRoutine.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class PrimitiveRoutine extends RuntimeEntity implements RoutineEntity {
+
+ private final Primitive primitive;
+
+ public PrimitiveRoutine(int size, Primitive primitive) {
+ super(size);
+ this.primitive = primitive;
+ }
+
+ public final Primitive getPrimitive() {
+ return primitive;
+ }
+
+ public void encodeCall(Emitter emitter, Frame frame) {
+ if (primitive != Primitive.ID) {
+ emitter.emit(OpCode.CALL, Register.PB, primitive);
+ }
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOADA, 0, Register.SB, 0);
+ emitter.emit(OpCode.LOADA, Register.PB, primitive);
+ }
+
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java
new file mode 100644
index 0000000..386aef5
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java
@@ -0,0 +1,11 @@
+package triangle.codeGenerator.entities;
+
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public interface RoutineEntity {
+
+ void encodeCall(Emitter emitter, Frame frame);
+
+ void encodeFetch(Emitter emitter, Frame frame);
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java
new file mode 100644
index 0000000..14540ee
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java
@@ -0,0 +1,30 @@
+/*
+ * @(#)RuntimeEntity.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+// Run-time object
+
+public abstract class RuntimeEntity {
+
+ private final int size;
+
+ protected RuntimeEntity(int size) {
+ this.size = size;
+ }
+
+ public final int getSize() {
+ return size;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java
new file mode 100644
index 0000000..1827025
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java
@@ -0,0 +1,23 @@
+/*
+ * @(#)TypeRepresentation.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+public class TypeRepresentation extends RuntimeEntity {
+
+ public TypeRepresentation(int size) {
+ super(size);
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java
new file mode 100644
index 0000000..af45996
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java
@@ -0,0 +1,74 @@
+/*
+ * @(#)UnknownAddress.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.Machine;
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class UnknownAddress extends AddressableEntity {
+
+ public UnknownAddress(int size, int level, int displacement) {
+ super(size, level, displacement);
+ }
+
+ public void encodeStore(Emitter emitter, Frame frame, int size, Vname vname) {
+
+ emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement());
+ if (vname.indexed) {
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+
+ int offset = vname.offset;
+ if (offset != 0) {
+ emitter.emit(OpCode.LOADL, 0, offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+ emitter.emit(OpCode.STOREI, size, 0);
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) {
+ emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement());
+
+ if (vname.indexed) {
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+
+ int offset = vname.offset;
+ if (offset != 0) {
+ emitter.emit(OpCode.LOADL, offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+ emitter.emit(OpCode.LOADI, size);
+ }
+
+ public void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname) {
+
+ emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement());
+ if (vname.indexed) {
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+
+ int offset = vname.offset;
+ if (offset != 0) {
+ emitter.emit(OpCode.LOADL, offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java
new file mode 100644
index 0000000..bb7fe26
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)UnknownRoutine.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.Machine;
+import triangle.abstractMachine.OpCode;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class UnknownRoutine extends RuntimeEntity implements RoutineEntity {
+
+ private final ObjectAddress address;
+
+ public UnknownRoutine(int size, int level, int displacement) {
+ super(size);
+ address = new ObjectAddress(level, displacement);
+ }
+
+ public final ObjectAddress getAddress() {
+ return address;
+ }
+
+ public void encodeCall(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOAD, Machine.closureSize, frame.getDisplayRegister(address), address.getDisplacement());
+ emitter.emit(OpCode.CALLI, 0);
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame) {
+ emitter.emit(OpCode.LOAD, Machine.closureSize, frame.getDisplayRegister(address), address.getDisplacement());
+ }
+
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java
new file mode 100644
index 0000000..7f4442f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java
@@ -0,0 +1,51 @@
+/*
+ * @(#)UnknownValue.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.codeGenerator.entities;
+
+import triangle.abstractMachine.OpCode;
+import triangle.abstractMachine.Primitive;
+import triangle.abstractMachine.Register;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+import triangle.codeGenerator.Emitter;
+import triangle.codeGenerator.Frame;
+
+public class UnknownValue extends RuntimeEntity implements FetchableEntity {
+
+ private final ObjectAddress address;
+
+ public UnknownValue(int size, int level, int displacement) {
+ super(size);
+ address = new ObjectAddress(level, displacement);
+ }
+
+ public UnknownValue(int size, Frame frame) {
+ this(size, frame.getLevel(), frame.getSize());
+ }
+
+ public final ObjectAddress getAddress() {
+ return address;
+ }
+
+ public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) {
+ if (vname.indexed) {
+ emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset);
+ emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD);
+ emitter.emit(OpCode.LOADI, size, 0);
+ } else {
+ emitter.emit(OpCode.LOAD, size, frame.getDisplayRegister(address),
+ address.getDisplacement() + vname.offset);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java
new file mode 100644
index 0000000..863b992
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java
@@ -0,0 +1,980 @@
+/*
+ * @(#)Checker.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.contextualAnalyzer;
+
+import triangle.ErrorReporter;
+import triangle.StdEnvironment;
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.Program;
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstantDeclaration;
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.FunctionDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcedureDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VariableDeclaration;
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.EmptyExpression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FormalParameter;
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.terminals.Terminal;
+import triangle.abstractSyntaxTrees.types.AnyTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.BoolTypeDenoter;
+import triangle.abstractSyntaxTrees.types.CharTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter;
+import triangle.abstractSyntaxTrees.types.FieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.IntTypeDenoter;
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor;
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.abstractSyntaxTrees.visitors.OperatorVisitor;
+import triangle.abstractSyntaxTrees.visitors.ProgramVisitor;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+import triangle.syntacticAnalyzer.SourcePosition;
+
+public final class Checker implements ActualParameterVisitor,
+ ActualParameterSequenceVisitor, ArrayAggregateVisitor,
+ CommandVisitor, DeclarationVisitor, ExpressionVisitor,
+ FormalParameterSequenceVisitor, IdentifierVisitor,
+ LiteralVisitor, OperatorVisitor, ProgramVisitor,
+ RecordAggregateVisitor, TypeDenoterVisitor,
+ VnameVisitor {
+
+ // Commands
+
+ // Always returns null. Does not use the given object.
+
+ @Override
+ public Void visitAssignCommand(AssignCommand ast, Void arg) {
+ var vType = ast.V.visit(this);
+ var eType = ast.E.visit(this);
+
+ checkAndReportError(ast.V.variable, "LHS of assignment is not a variable", ast.V);
+ checkAndReportError(eType.equals(vType), "assignment incompatibilty", ast);
+
+ return null;
+ }
+
+ @Override
+ public Void visitCallCommand(CallCommand ast, Void arg) {
+ var binding = ast.I.visit(this);
+
+ if (binding instanceof ProcedureDeclaration) {
+ ProcedureDeclaration procedure = (ProcedureDeclaration)binding;
+ ast.APS.visit(this, procedure.getFormals());
+ } else {
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier");
+ }
+
+ return null;
+ }
+
+ @Override
+ public Void visitEmptyCommand(EmptyCommand ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitIfCommand(IfCommand ast, Void arg) {
+ var eType = ast.E.visit(this);
+
+ checkAndReportError(eType.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E);
+
+ ast.C1.visit(this);
+ ast.C2.visit(this);
+
+ return null;
+ }
+
+ @Override
+ public Void visitLetCommand(LetCommand ast, Void arg) {
+ idTable.openScope();
+ ast.D.visit(this);
+ ast.C.visit(this);
+ idTable.closeScope();
+ return null;
+ }
+
+ @Override
+ public Void visitSequentialCommand(SequentialCommand ast, Void arg) {
+ ast.C1.visit(this);
+ ast.C2.visit(this);
+ return null;
+ }
+
+ @Override
+ public Void visitWhileCommand(WhileCommand ast, Void arg) {
+ var eType = ast.E.visit(this);
+
+ checkAndReportError(eType.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E);
+ ast.C.visit(this);
+
+ return null;
+ }
+
+ // Expressions
+
+ // Returns the TypeDenoter denoting the type of the expression. Does
+ // not use the given object.
+
+ @Override
+ public TypeDenoter visitArrayExpression(ArrayExpression ast, Void arg) {
+ var elemType = ast.AA.visit(this);
+ var il = new IntegerLiteral(Integer.toString(ast.AA.elemCount), ast.getPosition());
+ ast.type = new ArrayTypeDenoter(il, elemType, ast.getPosition());
+ return ast.type;
+ }
+
+ @Override
+ public TypeDenoter visitBinaryExpression(BinaryExpression ast, Void arg) {
+ var e1Type = ast.E1.visit(this);
+ var e2Type = ast.E2.visit(this);
+ var binding = ast.O.visit(this);
+
+ if (binding instanceof BinaryOperatorDeclaration) {
+ BinaryOperatorDeclaration bbinding = (BinaryOperatorDeclaration)binding;
+ if (bbinding.ARG1 == StdEnvironment.anyType) {
+ // this operator must be "=" or "\="
+ checkAndReportError(e1Type.equals(e2Type), "incompatible argument types for \"%\"", ast.O, ast);
+ } else {
+ checkAndReportError(e1Type.equals(bbinding.ARG1), "wrong argument type for \"%\"", ast.O, ast.E1);
+ checkAndReportError(e2Type.equals(bbinding.ARG2), "wrong argument type for \"%\"", ast.O, ast.E2);
+ }
+ return ast.type = bbinding.RES;
+ }
+
+ reportUndeclaredOrError(binding, ast.O, "\"%\" is not a binary operator");
+ return ast.type = StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitCallExpression(CallExpression ast, Void arg) {
+ var binding = ast.I.visit(this);
+
+ if (binding instanceof FunctionDeclaration) {
+ FunctionDeclaration function = (FunctionDeclaration)binding;
+ ast.APS.visit(this, function.getFormals());
+ return ast.type = function.getType();
+ }
+
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a function identifier");
+ return ast.type = StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitCharacterExpression(CharacterExpression ast, Void arg) {
+ return ast.type = StdEnvironment.charType;
+ }
+
+ @Override
+ public TypeDenoter visitEmptyExpression(EmptyExpression ast, Void arg) {
+ return ast.type = null;
+ }
+
+ @Override
+ public TypeDenoter visitIfExpression(IfExpression ast, Void arg) {
+ var e1Type = ast.E1.visit(this);
+ checkAndReportError(e1Type.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E1);
+
+ var e2Type = ast.E2.visit(this);
+ var e3Type = ast.E3.visit(this);
+ checkAndReportError(e2Type.equals(e3Type), "incompatible limbs in if-expression", ast);
+ return ast.type = e2Type;
+ }
+
+ @Override
+ public TypeDenoter visitIntegerExpression(IntegerExpression ast, Void arg) {
+ return ast.type = StdEnvironment.integerType;
+ }
+
+ @Override
+ public TypeDenoter visitLetExpression(LetExpression ast, Void arg) {
+ idTable.openScope();
+ ast.D.visit(this);
+ ast.type = ast.E.visit(this);
+ idTable.closeScope();
+ return ast.type;
+ }
+
+ @Override
+ public TypeDenoter visitRecordExpression(RecordExpression ast, Void arg) {
+ var rType = ast.RA.visit(this);
+ return ast.type = new RecordTypeDenoter(rType, ast.getPosition());
+ }
+
+ @Override
+ public TypeDenoter visitUnaryExpression(UnaryExpression ast, Void arg) {
+ var eType = ast.E.visit(this);
+ var binding = ast.O.visit(this);
+
+ if (binding instanceof UnaryOperatorDeclaration) {
+ UnaryOperatorDeclaration ubinding = (UnaryOperatorDeclaration)binding;
+ checkAndReportError(eType.equals(ubinding.ARG), "wrong argument type for \"%\"", ast.O);
+ return ast.type = ubinding.RES;
+ }
+
+ reportUndeclaredOrError(binding, ast.O, "\"%\" is not a unary operator");
+ return ast.type = StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitVnameExpression(VnameExpression ast, Void arg) {
+ return ast.type = ast.V.visit(this);
+ }
+
+ // Declarations
+
+ // Always returns null. Does not use the given object.
+ @Override
+ public Void visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitConstDeclaration(ConstDeclaration ast, Void arg) {
+ ast.E.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitFuncDeclaration(FuncDeclaration ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ // permits recursion
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast);
+
+ idTable.openScope();
+ ast.FPS.visit(this);
+ var eType = ast.E.visit(this);
+ idTable.closeScope();
+
+ checkAndReportError(ast.T.equals(eType), "body of function \"%\" has wrong type", ast.I, ast.E);
+ return null;
+ }
+
+ @Override
+ public Void visitProcDeclaration(ProcDeclaration ast, Void arg) {
+ // permits recursion
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast);
+
+ idTable.openScope();
+ ast.FPS.visit(this);
+ ast.C.visit(this);
+ idTable.closeScope();
+
+ return null;
+ }
+
+ @Override
+ public Void visitSequentialDeclaration(SequentialDeclaration ast, Void arg) {
+ ast.D1.visit(this);
+ ast.D2.visit(this);
+ return null;
+ }
+
+ @Override
+ public Void visitTypeDeclaration(TypeDeclaration ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitVarDeclaration(VarDeclaration ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast);
+ return null;
+ }
+
+ // Array Aggregates
+
+ // Returns the TypeDenoter for the Array Aggregate. Does not use the
+ // given object.
+
+ @Override
+ public TypeDenoter visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void arg) {
+ var eType = ast.E.visit(this);
+ var elemType = ast.AA.visit(this);
+ ast.elemCount = ast.AA.elemCount + 1;
+ checkAndReportError(eType.equals(elemType), "incompatible array-aggregate element", ast.E);
+ return elemType;
+ }
+
+ @Override
+ public TypeDenoter visitSingleArrayAggregate(SingleArrayAggregate ast, Void arg) {
+ var elemType = ast.E.visit(this);
+ ast.elemCount = 1;
+ return elemType;
+ }
+
+ // Record Aggregates
+
+ // Returns the TypeDenoter for the Record Aggregate. Does not use the
+ // given object.
+
+ @Override
+ public FieldTypeDenoter visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void arg) {
+ var eType = ast.E.visit(this);
+ var rType = ast.RA.visit(this);
+ var fType = checkFieldIdentifier(rType, ast.I);
+ checkAndReportError(fType.equals(StdEnvironment.errorType), "duplicate field \"%\" in record", ast.I);
+ return ast.type = new MultipleFieldTypeDenoter(ast.I, eType, rType, ast.getPosition());
+ }
+
+ @Override
+ public FieldTypeDenoter visitSingleRecordAggregate(SingleRecordAggregate ast, Void arg) {
+ var eType = ast.E.visit(this);
+ return ast.type = new SingleFieldTypeDenoter(ast.I, eType, ast.getPosition());
+ }
+
+ // Formal Parameters
+
+ // Always returns null. Does not use the given object.
+
+ @Override
+ public Void visitConstFormalParameter(ConstFormalParameter ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitFuncFormalParameter(FuncFormalParameter ast, Void arg) {
+ idTable.openScope();
+ ast.FPS.visit(this);
+ idTable.closeScope();
+ ast.T = ast.T.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitProcFormalParameter(ProcFormalParameter ast, Void arg) {
+ idTable.openScope();
+ ast.FPS.visit(this);
+ idTable.closeScope();
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitVarFormalParameter(VarFormalParameter ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ idTable.enter(ast.I.spelling, ast);
+ checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast);
+ return null;
+ }
+
+ @Override
+ public Void visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public Void visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void arg) {
+ ast.FP.visit(this);
+ ast.FPS.visit(this);
+ return null;
+ }
+
+ @Override
+ public Void visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void arg) {
+ ast.FP.visit(this);
+ return null;
+ }
+
+ // Actual Parameters
+
+ // Always returns null. Uses the given FormalParameter.
+
+ @Override
+ public Void visitConstActualParameter(ConstActualParameter ast, FormalParameter arg) {
+ var eType = ast.E.visit(this);
+ if (arg instanceof ConstFormalParameter) {
+ ConstFormalParameter param = (ConstFormalParameter)arg;
+ checkAndReportError(eType.equals(((ConstFormalParameter)arg).T), "wrong type for const actual parameter", ast.E);
+ } else {
+ reportError("const actual parameter not expected here", ast);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitFuncActualParameter(FuncActualParameter ast, FormalParameter arg) {
+ var binding = ast.I.visit(this);
+ if (binding instanceof FunctionDeclaration) {
+ FunctionDeclaration function = (FunctionDeclaration)binding;
+ var formals = function.getFormals();
+ var functionType = function.getType();
+ if (arg instanceof FuncFormalParameter) {
+ FuncFormalParameter param = (FuncFormalParameter)arg;
+ if (!formals.equals(param.getFormals())) {
+ reportError("wrong signature for function \"%\"", ast.I);
+ } else if (!functionType.equals(param.T)) {
+ reportError("wrong type for function \"%\"", ast.I);
+ }
+ } else {
+ reportError("func actual parameter not expected here", ast);
+ }
+ } else {
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a function identifier");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitProcActualParameter(ProcActualParameter ast, FormalParameter arg) {
+ var binding = ast.I.visit(this);
+ if (binding instanceof ProcedureDeclaration) {
+ ProcedureDeclaration procedure = (ProcedureDeclaration)binding;
+ var formals = procedure.getFormals();
+ if (arg instanceof ProcFormalParameter) {
+ ProcFormalParameter param = (ProcFormalParameter)arg;
+ checkAndReportError(formals.equals(param.getFormals()), "wrong signature for procedure \"%\"", ast.I);
+ } else {
+ reportError("proc actual parameter not expected here", ast);
+ }
+ } else {
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier");
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitVarActualParameter(VarActualParameter ast, FormalParameter arg) {
+ var vType = ast.V.visit(this);
+ if (!ast.V.variable) {
+ reportError("actual parameter is not a variable", ast.V);
+ } else if (arg instanceof VarFormalParameter) {
+ VarFormalParameter parameter = (VarFormalParameter)arg;
+ checkAndReportError(vType.equals(parameter.T), "wrong type for var actual parameter", ast.V);
+ } else {
+ reportError("var actual parameter not expected here", ast.V);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, FormalParameterSequence arg) {
+ checkAndReportError(arg instanceof EmptyFormalParameterSequence, "too few actual parameters", ast);
+ return null;
+ }
+
+ @Override
+ public Void visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, FormalParameterSequence arg) {
+ if (arg instanceof MultipleFormalParameterSequence) {
+ MultipleFormalParameterSequence formals = (MultipleFormalParameterSequence)arg;
+ ast.AP.visit(this, formals.FP);
+ ast.APS.visit(this, formals.FPS);
+ } else {
+ reportError("too many actual parameters", ast);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitSingleActualParameterSequence(SingleActualParameterSequence ast, FormalParameterSequence arg) {
+ if (arg instanceof SingleFormalParameterSequence) {
+ SingleFormalParameterSequence formal = (SingleFormalParameterSequence)arg;
+ ast.AP.visit(this, formal.FP);
+ } else {
+ reportError("incorrect number of actual parameters", ast);
+ }
+ return null;
+ }
+
+ // Type Denoters
+
+ // Returns the expanded version of the TypeDenoter. Does not
+ // use the given object.
+
+ @Override
+ public TypeDenoter visitAnyTypeDenoter(AnyTypeDenoter ast, Void arg) {
+ return StdEnvironment.anyType;
+ }
+
+ @Override
+ public TypeDenoter visitArrayTypeDenoter(ArrayTypeDenoter ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ checkAndReportError(ast.IL.getValue() != 0, "arrays must not be empty", ast.IL);
+ return ast;
+ }
+
+ @Override
+ public TypeDenoter visitBoolTypeDenoter(BoolTypeDenoter ast, Void arg) {
+ return StdEnvironment.booleanType;
+ }
+
+ @Override
+ public TypeDenoter visitCharTypeDenoter(CharTypeDenoter ast, Void arg) {
+ return StdEnvironment.charType;
+ }
+
+ @Override
+ public TypeDenoter visitErrorTypeDenoter(ErrorTypeDenoter ast, Void arg) {
+ return StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) {
+ var binding = ast.I.visit(this);
+ if (binding instanceof TypeDeclaration) {
+ TypeDeclaration decl = (TypeDeclaration)binding;
+ return decl.T;
+ }
+
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a type identifier");
+ return StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitIntTypeDenoter(IntTypeDenoter ast, Void arg) {
+ return StdEnvironment.integerType;
+ }
+
+ @Override
+ public TypeDenoter visitRecordTypeDenoter(RecordTypeDenoter ast, Void arg) {
+ ast.FT = (FieldTypeDenoter) ast.FT.visit(this);
+ return ast;
+ }
+
+ @Override
+ public TypeDenoter visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ ast.FT.visit(this);
+ return ast;
+ }
+
+ @Override
+ public TypeDenoter visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void arg) {
+ ast.T = ast.T.visit(this);
+ return ast;
+ }
+
+ // Literals, Identifiers and Operators
+ @Override
+ public TypeDenoter visitCharacterLiteral(CharacterLiteral CL, Void arg) {
+ return StdEnvironment.charType;
+ }
+
+ @Override
+ public Declaration visitIdentifier(Identifier I, Void arg) {
+ var binding = idTable.retrieve(I.spelling);
+ if (binding != null) {
+ I.decl = binding;
+ }
+ return binding;
+ }
+
+ @Override
+ public TypeDenoter visitIntegerLiteral(IntegerLiteral IL, Void arg) {
+ return StdEnvironment.integerType;
+ }
+
+ @Override
+ public Declaration visitOperator(Operator O, Void arg) {
+ var binding = idTable.retrieve(O.spelling);
+ if (binding != null) {
+ O.decl = binding;
+ }
+ return binding;
+ }
+
+ // Value-or-variable names
+
+ // Determines the address of a named object (constant or variable).
+ // This consists of a base object, to which 0 or more field-selection
+ // or array-indexing operations may be applied (if it is a record or
+ // array). As much as possible of the address computation is done at
+ // compile-time. Code is generated only when necessary to evaluate
+ // index expressions at run-time.
+ // currentLevel is the routine level where the v-name occurs.
+ // frameSize is the anticipated size of the local stack frame when
+ // the object is addressed at run-time.
+ // It returns the description of the base object.
+ // offset is set to the total of any field offsets (plus any offsets
+ // due to index expressions that happen to be literals).
+ // indexed is set to true iff there are any index expressions (other
+ // than literals). In that case code is generated to compute the
+ // offset due to these indexing operations at run-time.
+
+ // Returns the TypeDenoter of the Vname. Does not use the
+ // given object.
+
+ @Override
+ public TypeDenoter visitDotVname(DotVname ast, Void arg) {
+ ast.type = null;
+ var vType = ast.V.visit(this);
+ ast.variable = ast.V.variable;
+ if (vType instanceof RecordTypeDenoter) {
+ RecordTypeDenoter record = (RecordTypeDenoter)vType;
+ ast.type = checkFieldIdentifier(record.FT, ast.I);
+ checkAndReportError(ast.type != StdEnvironment.errorType, "no field \"%\" in this record type",
+ ast.I);
+ } else {
+ reportError("record expected here", ast.V);
+ }
+ return ast.type;
+ }
+
+ @Override
+ public TypeDenoter visitSimpleVname(SimpleVname ast, Void arg) {
+ ast.variable = false;
+ ast.type = StdEnvironment.errorType;
+
+ var binding = ast.I.visit(this);
+ if (binding instanceof ConstantDeclaration) {
+ ConstantDeclaration constant = (ConstantDeclaration)binding;
+ ast.variable = false;
+ return ast.type = constant.getType();
+ } else if (binding instanceof VariableDeclaration) {
+ VariableDeclaration variable = (VariableDeclaration)binding;
+ ast.variable = true;
+ return ast.type = variable.getType();
+ }
+
+ reportUndeclaredOrError(binding, ast.I, "\"%\" is not a const or var identifier");
+ return ast.type = StdEnvironment.errorType;
+ }
+
+ @Override
+ public TypeDenoter visitSubscriptVname(SubscriptVname ast, Void arg) {
+ var vType = ast.V.visit(this);
+ ast.variable = ast.V.variable;
+
+ var eType = ast.E.visit(this);
+ if (vType != StdEnvironment.errorType) {
+ if (vType instanceof ArrayTypeDenoter) {
+ ArrayTypeDenoter arrayType = (ArrayTypeDenoter)vType;
+ checkAndReportError(eType.equals(StdEnvironment.integerType), "Integer expression expected here",
+ ast.E);
+ ast.type = arrayType.T;
+ } else {
+ reportError("array expected here", ast.V);
+ }
+ }
+
+ return ast.type;
+ }
+
+ // Programs
+
+ @Override
+ public Void visitProgram(Program ast, Void arg) {
+ ast.C.visit(this);
+ return null;
+ }
+
+ // Checks whether the source program, represented by its AST, satisfies the
+ // language's scope rules and type rules.
+ // Also decorates the AST as follows:
+ // (a) Each applied occurrence of an identifier or operator is linked to
+ // the corresponding declaration of that identifier or operator.
+ // (b) Each expression and value-or-variable-name is decorated by its type.
+ // (c) Each type identifier is replaced by the type it denotes.
+ // Types are represented by small ASTs.
+
+ public void check(Program ast) {
+ ast.visit(this);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ public Checker(ErrorReporter reporter) {
+ this.reporter = reporter;
+ this.idTable = new IdentificationTable();
+ establishStdEnvironment();
+ }
+
+ private IdentificationTable idTable;
+ private static SourcePosition dummyPos = new SourcePosition();
+ private ErrorReporter reporter;
+
+ private void reportUndeclaredOrError(Declaration binding, Terminal leaf, String message) {
+ if (binding == null) {
+ reportError("\"%\" is not declared", leaf);
+ } else {
+ reportError(message, leaf);
+ }
+ }
+
+ private void reportError(String message, Terminal ast) {
+ reportError(message, ast, ast);
+ }
+
+ private void reportError(String message, Terminal spellingNode, AbstractSyntaxTree positionNode) {
+ reporter.reportError(message, spellingNode.spelling, positionNode.getPosition());
+ }
+
+ private void reportError(String message, AbstractSyntaxTree positionNode) {
+ reporter.reportError(message, "", positionNode.getPosition());
+ }
+
+ private void checkAndReportError(boolean condition, String message, String token, SourcePosition position) {
+ if (!condition) {
+ reporter.reportError(message, token, position);
+ }
+ }
+
+ private void checkAndReportError(boolean condition, String message, Terminal ast) {
+ checkAndReportError(condition, message, ast, ast);
+ }
+
+ private void checkAndReportError(boolean condition, String message, Terminal spellingNode,
+ AbstractSyntaxTree positionNode) {
+ checkAndReportError(condition, message, spellingNode.spelling, positionNode.getPosition());
+ }
+
+ private void checkAndReportError(boolean condition, String message, AbstractSyntaxTree positionNode) {
+ checkAndReportError(condition, message, "", positionNode.getPosition());
+ }
+
+ private static TypeDenoter checkFieldIdentifier(FieldTypeDenoter ast, Identifier I) {
+ if (ast instanceof MultipleFieldTypeDenoter) {
+ MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter)ast;
+ if (ft.I.spelling.compareTo(I.spelling) == 0) {
+ I.decl = ast;
+ return ft.T;
+ } else {
+ return checkFieldIdentifier(ft.FT, I);
+ }
+ } else if (ast instanceof SingleFieldTypeDenoter) {
+ SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter)ast;
+ if (ft.I.spelling.compareTo(I.spelling) == 0) {
+ I.decl = ast;
+ return ft.T;
+ }
+ }
+ return StdEnvironment.errorType;
+ }
+
+ // Creates a small AST to represent the "declaration" of a standard
+ // type, and enters it in the identification table.
+
+ private TypeDeclaration declareStdType(String id, TypeDenoter typedenoter) {
+
+ var binding = new TypeDeclaration(new Identifier(id, dummyPos), typedenoter, dummyPos);
+ idTable.enter(id, binding);
+ return binding;
+ }
+
+ // Creates a small AST to represent the "declaration" of a standard
+ // type, and enters it in the identification table.
+
+ private ConstDeclaration declareStdConst(String id, TypeDenoter constType) {
+
+ // constExpr used only as a placeholder for constType
+ var constExpr = new IntegerExpression(null, dummyPos);
+ constExpr.type = constType;
+ var binding = new ConstDeclaration(new Identifier(id, dummyPos), constExpr, dummyPos);
+ idTable.enter(id, binding);
+ return binding;
+ }
+
+ // Creates a small AST to represent the "declaration" of a standard
+ // type, and enters it in the identification table.
+
+ private ProcDeclaration declareStdProc(String id, FormalParameterSequence fps) {
+
+ var binding = new ProcDeclaration(new Identifier(id, dummyPos), fps, new EmptyCommand(dummyPos), dummyPos);
+ idTable.enter(id, binding);
+ return binding;
+ }
+
+ // Creates a small AST to represent the "declaration" of a standard
+ // type, and enters it in the identification table.
+
+ private FuncDeclaration declareStdFunc(String id, FormalParameterSequence fps, TypeDenoter resultType) {
+
+ var binding = new FuncDeclaration(new Identifier(id, dummyPos), fps, resultType, new EmptyExpression(dummyPos),
+ dummyPos);
+ idTable.enter(id, binding);
+ return binding;
+ }
+
+ // Creates a small AST to represent the "declaration" of a
+ // unary operator, and enters it in the identification table.
+ // This "declaration" summarises the operator's type info.
+
+ private UnaryOperatorDeclaration declareStdUnaryOp(String op, TypeDenoter argType, TypeDenoter resultType) {
+
+ var binding = new UnaryOperatorDeclaration(new Operator(op, dummyPos), argType, resultType, dummyPos);
+ idTable.enter(op, binding);
+ return binding;
+ }
+
+ // Creates a small AST to represent the "declaration" of a
+ // binary operator, and enters it in the identification table.
+ // This "declaration" summarises the operator's type info.
+
+ private BinaryOperatorDeclaration declareStdBinaryOp(String op, TypeDenoter arg1Type, TypeDenoter arg2type,
+ TypeDenoter resultType) {
+
+ var binding = new BinaryOperatorDeclaration(new Operator(op, dummyPos), arg1Type, arg2type, resultType,
+ dummyPos);
+ idTable.enter(op, binding);
+ return binding;
+ }
+
+ // Creates small ASTs to represent the standard types.
+ // Creates small ASTs to represent "declarations" of standard types,
+ // constants, procedures, functions, and operators.
+ // Enters these "declarations" in the identification table.
+
+ private final static Identifier dummyI = new Identifier("", dummyPos);
+
+ private void establishStdEnvironment() {
+
+ // idTable.startIdentification();
+ StdEnvironment.booleanType = new BoolTypeDenoter(dummyPos);
+ StdEnvironment.integerType = new IntTypeDenoter(dummyPos);
+ StdEnvironment.charType = new CharTypeDenoter(dummyPos);
+ StdEnvironment.anyType = new AnyTypeDenoter(dummyPos);
+ StdEnvironment.errorType = new ErrorTypeDenoter(dummyPos);
+
+ StdEnvironment.booleanDecl = declareStdType("Boolean", StdEnvironment.booleanType);
+ StdEnvironment.falseDecl = declareStdConst("false", StdEnvironment.booleanType);
+ StdEnvironment.trueDecl = declareStdConst("true", StdEnvironment.booleanType);
+ StdEnvironment.notDecl = declareStdUnaryOp("\\", StdEnvironment.booleanType, StdEnvironment.booleanType);
+ StdEnvironment.andDecl = declareStdBinaryOp("/\\", StdEnvironment.booleanType, StdEnvironment.booleanType,
+ StdEnvironment.booleanType);
+ StdEnvironment.orDecl = declareStdBinaryOp("\\/", StdEnvironment.booleanType, StdEnvironment.booleanType,
+ StdEnvironment.booleanType);
+
+ StdEnvironment.integerDecl = declareStdType("Integer", StdEnvironment.integerType);
+ StdEnvironment.maxintDecl = declareStdConst("maxint", StdEnvironment.integerType);
+ StdEnvironment.addDecl = declareStdBinaryOp("+", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.integerType);
+ StdEnvironment.subtractDecl = declareStdBinaryOp("-", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.integerType);
+ StdEnvironment.multiplyDecl = declareStdBinaryOp("*", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.integerType);
+ StdEnvironment.divideDecl = declareStdBinaryOp("/", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.integerType);
+ StdEnvironment.moduloDecl = declareStdBinaryOp("//", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.integerType);
+ StdEnvironment.lessDecl = declareStdBinaryOp("<", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.booleanType);
+ StdEnvironment.notgreaterDecl = declareStdBinaryOp("<=", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.booleanType);
+ StdEnvironment.greaterDecl = declareStdBinaryOp(">", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.booleanType);
+ StdEnvironment.notlessDecl = declareStdBinaryOp(">=", StdEnvironment.integerType, StdEnvironment.integerType,
+ StdEnvironment.booleanType);
+
+ StdEnvironment.charDecl = declareStdType("Char", StdEnvironment.charType);
+ StdEnvironment.chrDecl = declareStdFunc("chr",
+ new SingleFormalParameterSequence(
+ new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos),
+ StdEnvironment.charType);
+ StdEnvironment.ordDecl = declareStdFunc("ord",
+ new SingleFormalParameterSequence(new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos),
+ dummyPos),
+ StdEnvironment.integerType);
+ StdEnvironment.eofDecl = declareStdFunc("eof", new EmptyFormalParameterSequence(dummyPos),
+ StdEnvironment.booleanType);
+ StdEnvironment.eolDecl = declareStdFunc("eol", new EmptyFormalParameterSequence(dummyPos),
+ StdEnvironment.booleanType);
+ StdEnvironment.getDecl = declareStdProc("get", new SingleFormalParameterSequence(
+ new VarFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos));
+ StdEnvironment.putDecl = declareStdProc("put", new SingleFormalParameterSequence(
+ new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos));
+ StdEnvironment.getintDecl = declareStdProc("getint", new SingleFormalParameterSequence(
+ new VarFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos));
+ StdEnvironment.putintDecl = declareStdProc("putint", new SingleFormalParameterSequence(
+ new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos));
+ StdEnvironment.geteolDecl = declareStdProc("geteol", new EmptyFormalParameterSequence(dummyPos));
+ StdEnvironment.puteolDecl = declareStdProc("puteol", new EmptyFormalParameterSequence(dummyPos));
+ StdEnvironment.equalDecl = declareStdBinaryOp("=", StdEnvironment.anyType, StdEnvironment.anyType,
+ StdEnvironment.booleanType);
+ StdEnvironment.unequalDecl = declareStdBinaryOp("\\=", StdEnvironment.anyType, StdEnvironment.anyType,
+ StdEnvironment.booleanType);
+
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java
new file mode 100644
index 0000000..7e6a153
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)IdEntry.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.contextualAnalyzer;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+
+public class IdEntry {
+
+ protected String id;
+ protected Declaration attr;
+ protected int level;
+ protected IdEntry previous;
+
+ IdEntry(String id, Declaration attr, int level, IdEntry previous) {
+ this.id = id;
+ this.attr = attr;
+ this.level = level;
+ this.previous = previous;
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java
new file mode 100644
index 0000000..33d1157
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java
@@ -0,0 +1,87 @@
+/*
+ * @(#)IdentificationTable.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.contextualAnalyzer;
+
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+
+public final class IdentificationTable {
+
+ private int level;
+ private IdEntry latest;
+
+ public IdentificationTable() {
+ level = 0;
+ latest = null;
+ }
+
+ // Opens a new level in the identification table, 1 higher than the
+ // current topmost level.
+
+ public void openScope() {
+ level++;
+ }
+
+ // Closes the topmost level in the identification table, discarding
+ // all entries belonging to that level.
+
+ public void closeScope() {
+ // Presumably, idTable.level > 0.
+ var entry = this.latest;
+ while (entry.level == this.level) {
+ entry = entry.previous;
+ }
+
+ this.level--;
+ this.latest = entry;
+ }
+
+ // Makes a new entry in the identification table for the given identifier
+ // and attribute. The new entry belongs to the current level.
+ // duplicated is set to to true iff there is already an entry for the
+ // same identifier at the current level.
+
+ public void enter(String id, Declaration attr) {
+ attr.duplicated = retrieve(id, true) != null;
+ this.latest = new IdEntry(id, attr, this.level, this.latest);
+ }
+
+ // Finds an entry for the given identifier in the identification table,
+ // if any. If there are several entries for that identifier, finds the
+ // entry at the highest level, in accordance with the scope rules.
+ // Returns null iff no entry is found.
+ // otherwise returns the attribute field of the entry found.
+
+ public Declaration retrieve(String id) {
+ return retrieve(id, false);
+ }
+
+ // thisLevelOnly limits the search to only the current level
+
+ public Declaration retrieve(String id, boolean thisLevelOnly) {
+ var entry = this.latest;
+ while (true) {
+ if (entry == null || (thisLevelOnly && entry.level < this.level)) {
+ break;
+ } else if (entry.id.equals(id)) {
+ return entry.attr;
+ } else {
+ entry = entry.previous;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java b/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java
new file mode 100644
index 0000000..1ba56ea
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java
@@ -0,0 +1,599 @@
+package triangle.optimiser;
+
+import triangle.StdEnvironment;
+import triangle.abstractSyntaxTrees.AbstractSyntaxTree;
+import triangle.abstractSyntaxTrees.Program;
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.EmptyExpression;
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.AnyTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.BoolTypeDenoter;
+import triangle.abstractSyntaxTrees.types.CharTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter;
+import triangle.abstractSyntaxTrees.types.IntTypeDenoter;
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor;
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.abstractSyntaxTrees.visitors.OperatorVisitor;
+import triangle.abstractSyntaxTrees.visitors.ProgramVisitor;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+
+public class ConstantFolder implements ActualParameterVisitor,
+ ActualParameterSequenceVisitor, ArrayAggregateVisitor,
+ CommandVisitor, DeclarationVisitor,
+ ExpressionVisitor, FormalParameterSequenceVisitor,
+ IdentifierVisitor, LiteralVisitor,
+ OperatorVisitor, ProgramVisitor,
+ RecordAggregateVisitor, TypeDenoterVisitor,
+ VnameVisitor {
+ {
+
+ }
+
+ @Override
+ public AbstractSyntaxTree visitConstFormalParameter(ConstFormalParameter ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitFuncFormalParameter(FuncFormalParameter ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitProcFormalParameter(ProcFormalParameter ast, Void arg) {
+ ast.I.visit(this);
+ ast.FPS.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitVarFormalParameter(VarFormalParameter ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void arg) {
+ ast.FT.visit(this);
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitDotVname(DotVname ast, Void arg) {
+ ast.I.visit(this);
+ ast.V.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSimpleVname(SimpleVname ast, Void arg) {
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSubscriptVname(SubscriptVname ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.V.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitAnyTypeDenoter(AnyTypeDenoter ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitArrayTypeDenoter(ArrayTypeDenoter ast, Void arg) {
+ ast.IL.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitBoolTypeDenoter(BoolTypeDenoter ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitCharTypeDenoter(CharTypeDenoter ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitErrorTypeDenoter(ErrorTypeDenoter ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) {
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIntTypeDenoter(IntTypeDenoter ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitRecordTypeDenoter(RecordTypeDenoter ast, Void arg) {
+ ast.FT.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.I.visit(this);
+ ast.RA.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSingleRecordAggregate(SingleRecordAggregate ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitProgram(Program ast, Void arg) {
+ ast.C.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitOperator(Operator ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitCharacterLiteral(CharacterLiteral ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIntegerLiteral(IntegerLiteral ast, Void arg) {
+ return ast;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIdentifier(Identifier ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void arg) {
+ ast.FP.visit(this);
+ ast.FPS.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void arg) {
+ ast.FP.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitArrayExpression(ArrayExpression ast, Void arg) {
+ ast.AA.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitBinaryExpression(BinaryExpression ast, Void arg) {
+ AbstractSyntaxTree replacement1 = ast.E1.visit(this);
+ AbstractSyntaxTree replacement2 = ast.E2.visit(this);
+ ast.O.visit(this);
+
+ // if visiting a child node returns something, it's either the original constant
+ // (IntegerLiteral) or a folded version replacing the expression at that child
+ // node
+ // If both child nodes are not null; return a folded version of this
+ // BinaryExpression
+ // Otherwise, at least one child node isn't constant (foldable) so just replace
+ // the
+ // foldable child nodes with their folded equivalent and return null
+ if (replacement1 != null && replacement2 != null) {
+ return foldBinaryExpression(replacement1, replacement2, ast.O);
+ } else if (replacement1 != null) {
+ ast.E1 = (Expression) replacement1;
+ } else if (replacement2 != null) {
+ ast.E2 = (Expression) replacement2;
+ }
+
+ // if we get here, we can't fold any higher than this level
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitCallExpression(CallExpression ast, Void arg) {
+ ast.APS.visit(this);
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitCharacterExpression(CharacterExpression ast, Void arg) {
+ ast.CL.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitEmptyExpression(EmptyExpression ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIfExpression(IfExpression ast, Void arg) {
+ AbstractSyntaxTree replacement1 = ast.E1.visit(this);
+ if (replacement1 != null) {
+ ast.E1 = (Expression) replacement1;
+ }
+ AbstractSyntaxTree replacement2 = ast.E2.visit(this);
+ if (replacement2 != null) {
+ ast.E2 = (Expression) replacement2;
+ }
+ AbstractSyntaxTree replacement3 = ast.E3.visit(this);
+ if (replacement3 != null) {
+ ast.E3 = (Expression) replacement3;
+ }
+
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIntegerExpression(IntegerExpression ast, Void arg) {
+ return ast;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitLetExpression(LetExpression ast, Void arg) {
+ ast.D.visit(this);
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitRecordExpression(RecordExpression ast, Void arg) {
+ ast.RA.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitUnaryExpression(UnaryExpression ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+
+ ast.O.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitVnameExpression(VnameExpression ast, Void arg) {
+ ast.V.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void arg) {
+ ast.ARG1.visit(this);
+ ast.ARG2.visit(this);
+ ast.O.visit(this);
+ ast.RES.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitConstDeclaration(ConstDeclaration ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitFuncDeclaration(FuncDeclaration ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.FPS.visit(this);
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitProcDeclaration(ProcDeclaration ast, Void arg) {
+ ast.C.visit(this);
+ ast.FPS.visit(this);
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSequentialDeclaration(SequentialDeclaration ast, Void arg) {
+ ast.D1.visit(this);
+ ast.D2.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitTypeDeclaration(TypeDeclaration ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void arg) {
+ ast.ARG.visit(this);
+ ast.O.visit(this);
+ ast.RES.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitVarDeclaration(VarDeclaration ast, Void arg) {
+ ast.I.visit(this);
+ ast.T.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitAssignCommand(AssignCommand ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ ast.V.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitCallCommand(CallCommand ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitEmptyCommand(EmptyCommand ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitIfCommand(IfCommand ast, Void arg) {
+ ast.C1.visit(this);
+ ast.C2.visit(this);
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitLetCommand(LetCommand ast, Void arg) {
+ ast.C.visit(this);
+ ast.D.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSequentialCommand(SequentialCommand ast, Void arg) {
+ ast.C1.visit(this);
+ ast.C2.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitWhileCommand(WhileCommand ast, Void arg) {
+ ast.C.visit(this);
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ // TODO uncomment if you've implemented the repeat command
+// @Override
+// public AbstractSyntaxTree visitRepeatCommand(RepeatCommand ast, Void arg) {
+// ast.C.visit(this);
+// AbstractSyntaxTree replacement = ast.E.visit(this);
+// if (replacement != null) {
+// ast.E = (Expression) replacement;
+// }
+// return null;
+// }
+
+ @Override
+ public AbstractSyntaxTree visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void arg) {
+ ast.AA.visit(this);
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSingleArrayAggregate(SingleArrayAggregate ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Void arg) {
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Void arg) {
+ ast.AP.visit(this);
+ ast.APS.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitSingleActualParameterSequence(SingleActualParameterSequence ast, Void arg) {
+ ast.AP.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitConstActualParameter(ConstActualParameter ast, Void arg) {
+ AbstractSyntaxTree replacement = ast.E.visit(this);
+ if (replacement != null) {
+ ast.E = (Expression) replacement;
+ }
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitFuncActualParameter(FuncActualParameter ast, Void arg) {
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitProcActualParameter(ProcActualParameter ast, Void arg) {
+ ast.I.visit(this);
+ return null;
+ }
+
+ @Override
+ public AbstractSyntaxTree visitVarActualParameter(VarActualParameter ast, Void arg) {
+ ast.V.visit(this);
+ return null;
+ }
+
+ public AbstractSyntaxTree foldBinaryExpression(AbstractSyntaxTree node1, AbstractSyntaxTree node2, Operator o) {
+ // the only case we know how to deal with for now is two IntegerExpressions
+ if ((node1 instanceof IntegerExpression) && (node2 instanceof IntegerExpression)) {
+ int int1 = (Integer.parseInt(((IntegerExpression) node1).IL.spelling));
+ int int2 = (Integer.parseInt(((IntegerExpression) node2).IL.spelling));
+ Object foldedValue = null;
+
+ if (o.decl == StdEnvironment.addDecl) {
+ foldedValue = int1 + int2;
+ }
+
+ if (foldedValue instanceof Integer) {
+ IntegerLiteral il = new IntegerLiteral(foldedValue.toString(), node1.getPosition());
+ IntegerExpression ie = new IntegerExpression(il, node1.getPosition());
+ ie.type = StdEnvironment.integerType;
+ return ie;
+ } else if (foldedValue instanceof Boolean) {
+ /* currently not handled! */
+ }
+ }
+
+ // any unhandled situation (i.e., not foldable) is ignored
+ return null;
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java
new file mode 100644
index 0000000..3cccb6b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java
@@ -0,0 +1,920 @@
+/*
+ * @(#)Parser.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+import triangle.ErrorReporter;
+import triangle.abstractSyntaxTrees.Program;
+import triangle.abstractSyntaxTrees.actuals.ActualParameter;
+import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+import triangle.abstractSyntaxTrees.aggregates.ArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.RecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.Command;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.Declaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.Expression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FormalParameter;
+import triangle.abstractSyntaxTrees.formals.FormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.FieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.types.TypeDenoter;
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+import triangle.abstractSyntaxTrees.vnames.Vname;
+
+public class Parser {
+
+ private Scanner lexicalAnalyser;
+ private ErrorReporter errorReporter;
+ private Token currentToken;
+ private SourcePosition previousTokenPosition;
+
+ public Parser(Scanner lexer, ErrorReporter reporter) {
+ lexicalAnalyser = lexer;
+ errorReporter = reporter;
+ previousTokenPosition = new SourcePosition();
+ }
+
+ // accept checks whether the current token matches tokenExpected.
+ // If so, fetches the next token.
+ // If not, reports a syntactic error.
+
+ void accept(int tokenExpected) throws SyntaxError {
+ if (currentToken.kind == tokenExpected) {
+ previousTokenPosition = currentToken.position;
+ currentToken = lexicalAnalyser.scan();
+ } else {
+ syntacticError("\"%\" expected here", Token.spell(tokenExpected));
+ }
+ }
+
+ void acceptIt() {
+ previousTokenPosition = currentToken.position;
+ currentToken = lexicalAnalyser.scan();
+ }
+
+ // start records the position of the start of a phrase.
+ // This is defined to be the position of the first
+ // character of the first token of the phrase.
+
+ void start(SourcePosition position) {
+ position.start = currentToken.position.start;
+ }
+
+ // finish records the position of the end of a phrase.
+ // This is defined to be the position of the last
+ // character of the last token of the phrase.
+
+ void finish(SourcePosition position) {
+ position.finish = previousTokenPosition.finish;
+ }
+
+ void syntacticError(String messageTemplate, String tokenQuoted) throws SyntaxError {
+ SourcePosition pos = currentToken.position;
+ errorReporter.reportError(messageTemplate, tokenQuoted, pos);
+ throw (new SyntaxError());
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // PROGRAMS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ public Program parseProgram() {
+
+ Program programAST = null;
+
+ previousTokenPosition.start = 0;
+ previousTokenPosition.finish = 0;
+ currentToken = lexicalAnalyser.scan();
+
+ try {
+ Command cAST = parseCommand();
+ programAST = new Program(cAST, previousTokenPosition);
+ if (currentToken.kind != Token.EOT) {
+ syntacticError("\"%\" not expected after end of program", currentToken.spelling);
+ }
+ } catch (SyntaxError s) {
+ return null;
+ }
+ return programAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // LITERALS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // parseIntegerLiteral parses an integer-literal, and constructs
+ // a leaf AST to represent it.
+
+ IntegerLiteral parseIntegerLiteral() throws SyntaxError {
+ IntegerLiteral IL = null;
+
+ if (currentToken.kind == Token.INTLITERAL) {
+ previousTokenPosition = currentToken.position;
+ String spelling = currentToken.spelling;
+ IL = new IntegerLiteral(spelling, previousTokenPosition);
+ currentToken = lexicalAnalyser.scan();
+ } else {
+ IL = null;
+ syntacticError("integer literal expected here", "");
+ }
+ return IL;
+ }
+
+ // parseCharacterLiteral parses a character-literal, and constructs a leaf
+ // AST to represent it.
+
+ CharacterLiteral parseCharacterLiteral() throws SyntaxError {
+ CharacterLiteral CL = null;
+
+ if (currentToken.kind == Token.CHARLITERAL) {
+ previousTokenPosition = currentToken.position;
+ String spelling = currentToken.spelling;
+ CL = new CharacterLiteral(spelling, previousTokenPosition);
+ currentToken = lexicalAnalyser.scan();
+ } else {
+ CL = null;
+ syntacticError("character literal expected here", "");
+ }
+ return CL;
+ }
+
+ // parseIdentifier parses an identifier, and constructs a leaf AST to
+ // represent it.
+
+ Identifier parseIdentifier() throws SyntaxError {
+ Identifier I = null;
+
+ if (currentToken.kind == Token.IDENTIFIER) {
+ previousTokenPosition = currentToken.position;
+ String spelling = currentToken.spelling;
+ I = new Identifier(spelling, previousTokenPosition);
+ currentToken = lexicalAnalyser.scan();
+ } else {
+ I = null;
+ syntacticError("identifier expected here", "");
+ }
+ return I;
+ }
+
+ // parseOperator parses an operator, and constructs a leaf AST to
+ // represent it.
+
+ Operator parseOperator() throws SyntaxError {
+ Operator O = null;
+
+ if (currentToken.kind == Token.OPERATOR) {
+ previousTokenPosition = currentToken.position;
+ String spelling = currentToken.spelling;
+ O = new Operator(spelling, previousTokenPosition);
+ currentToken = lexicalAnalyser.scan();
+ } else {
+ O = null;
+ syntacticError("operator expected here", "");
+ }
+ return O;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // COMMANDS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // parseCommand parses the command, and constructs an AST
+ // to represent its phrase structure.
+
+ Command parseCommand() throws SyntaxError {
+ Command commandAST = null; // in case there's a syntactic error
+
+ SourcePosition commandPos = new SourcePosition();
+
+ start(commandPos);
+ commandAST = parseSingleCommand();
+ while (currentToken.kind == Token.SEMICOLON) {
+ acceptIt();
+ Command c2AST = parseSingleCommand();
+ finish(commandPos);
+ commandAST = new SequentialCommand(commandAST, c2AST, commandPos);
+ }
+ return commandAST;
+ }
+
+ Command parseSingleCommand() throws SyntaxError {
+ Command commandAST = null; // in case there's a syntactic error
+
+ SourcePosition commandPos = new SourcePosition();
+ start(commandPos);
+
+ switch (currentToken.kind) {
+
+ case Token.IDENTIFIER: {
+ Identifier iAST = parseIdentifier();
+ if (currentToken.kind == Token.LPAREN) {
+ acceptIt();
+ ActualParameterSequence apsAST = parseActualParameterSequence();
+ accept(Token.RPAREN);
+ finish(commandPos);
+ commandAST = new CallCommand(iAST, apsAST, commandPos);
+
+ } else {
+
+ Vname vAST = parseRestOfVname(iAST);
+ accept(Token.BECOMES);
+ Expression eAST = parseExpression();
+ finish(commandPos);
+ commandAST = new AssignCommand(vAST, eAST, commandPos);
+ }
+ }
+ break;
+
+ case Token.BEGIN:
+ acceptIt();
+ commandAST = parseCommand();
+ accept(Token.END);
+ break;
+
+ case Token.LET: {
+ acceptIt();
+ Declaration dAST = parseDeclaration();
+ accept(Token.IN);
+ Command cAST = parseSingleCommand();
+ finish(commandPos);
+ commandAST = new LetCommand(dAST, cAST, commandPos);
+ }
+ break;
+
+ case Token.IF: {
+ acceptIt();
+ Expression eAST = parseExpression();
+ accept(Token.THEN);
+ Command c1AST = parseSingleCommand();
+ accept(Token.ELSE);
+ Command c2AST = parseSingleCommand();
+ finish(commandPos);
+ commandAST = new IfCommand(eAST, c1AST, c2AST, commandPos);
+ }
+ break;
+
+ case Token.WHILE: {
+ acceptIt();
+ Expression eAST = parseExpression();
+ accept(Token.DO);
+ Command cAST = parseSingleCommand();
+ finish(commandPos);
+ commandAST = new WhileCommand(eAST, cAST, commandPos);
+ }
+ break;
+
+ case Token.SEMICOLON:
+ case Token.END:
+ case Token.ELSE:
+ case Token.IN:
+ case Token.EOT:
+
+ finish(commandPos);
+ commandAST = new EmptyCommand(commandPos);
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start a command", currentToken.spelling);
+ break;
+
+ }
+
+ return commandAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // EXPRESSIONS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ Expression parseExpression() throws SyntaxError {
+ Expression expressionAST = null; // in case there's a syntactic error
+
+ SourcePosition expressionPos = new SourcePosition();
+
+ start(expressionPos);
+
+ switch (currentToken.kind) {
+
+ case Token.LET: {
+ acceptIt();
+ Declaration dAST = parseDeclaration();
+ accept(Token.IN);
+ Expression eAST = parseExpression();
+ finish(expressionPos);
+ expressionAST = new LetExpression(dAST, eAST, expressionPos);
+ }
+ break;
+
+ case Token.IF: {
+ acceptIt();
+ Expression e1AST = parseExpression();
+ accept(Token.THEN);
+ Expression e2AST = parseExpression();
+ accept(Token.ELSE);
+ Expression e3AST = parseExpression();
+ finish(expressionPos);
+ expressionAST = new IfExpression(e1AST, e2AST, e3AST, expressionPos);
+ }
+ break;
+
+ default:
+ expressionAST = parseSecondaryExpression();
+ break;
+ }
+ return expressionAST;
+ }
+
+ Expression parseSecondaryExpression() throws SyntaxError {
+ Expression expressionAST = null; // in case there's a syntactic error
+
+ SourcePosition expressionPos = new SourcePosition();
+ start(expressionPos);
+
+ expressionAST = parsePrimaryExpression();
+ while (currentToken.kind == Token.OPERATOR) {
+ Operator opAST = parseOperator();
+ Expression e2AST = parsePrimaryExpression();
+ expressionAST = new BinaryExpression(expressionAST, opAST, e2AST, expressionPos);
+ }
+ return expressionAST;
+ }
+
+ Expression parsePrimaryExpression() throws SyntaxError {
+ Expression expressionAST = null; // in case there's a syntactic error
+
+ SourcePosition expressionPos = new SourcePosition();
+ start(expressionPos);
+
+ switch (currentToken.kind) {
+
+ case Token.INTLITERAL: {
+ IntegerLiteral ilAST = parseIntegerLiteral();
+ finish(expressionPos);
+ expressionAST = new IntegerExpression(ilAST, expressionPos);
+ }
+ break;
+
+ case Token.CHARLITERAL: {
+ CharacterLiteral clAST = parseCharacterLiteral();
+ finish(expressionPos);
+ expressionAST = new CharacterExpression(clAST, expressionPos);
+ }
+ break;
+
+ case Token.LBRACKET: {
+ acceptIt();
+ ArrayAggregate aaAST = parseArrayAggregate();
+ accept(Token.RBRACKET);
+ finish(expressionPos);
+ expressionAST = new ArrayExpression(aaAST, expressionPos);
+ }
+ break;
+
+ case Token.LCURLY: {
+ acceptIt();
+ RecordAggregate raAST = parseRecordAggregate();
+ accept(Token.RCURLY);
+ finish(expressionPos);
+ expressionAST = new RecordExpression(raAST, expressionPos);
+ }
+ break;
+
+ case Token.IDENTIFIER: {
+ Identifier iAST = parseIdentifier();
+ if (currentToken.kind == Token.LPAREN) {
+ acceptIt();
+ ActualParameterSequence apsAST = parseActualParameterSequence();
+ accept(Token.RPAREN);
+ finish(expressionPos);
+ expressionAST = new CallExpression(iAST, apsAST, expressionPos);
+
+ } else {
+ Vname vAST = parseRestOfVname(iAST);
+ finish(expressionPos);
+ expressionAST = new VnameExpression(vAST, expressionPos);
+ }
+ }
+ break;
+
+ case Token.OPERATOR: {
+ Operator opAST = parseOperator();
+ Expression eAST = parsePrimaryExpression();
+ finish(expressionPos);
+ expressionAST = new UnaryExpression(opAST, eAST, expressionPos);
+ }
+ break;
+
+ case Token.LPAREN:
+ acceptIt();
+ expressionAST = parseExpression();
+ accept(Token.RPAREN);
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start an expression", currentToken.spelling);
+ break;
+
+ }
+ return expressionAST;
+ }
+
+ RecordAggregate parseRecordAggregate() throws SyntaxError {
+ RecordAggregate aggregateAST = null; // in case there's a syntactic error
+
+ SourcePosition aggregatePos = new SourcePosition();
+ start(aggregatePos);
+
+ Identifier iAST = parseIdentifier();
+ accept(Token.IS);
+ Expression eAST = parseExpression();
+
+ if (currentToken.kind == Token.COMMA) {
+ acceptIt();
+ RecordAggregate aAST = parseRecordAggregate();
+ finish(aggregatePos);
+ aggregateAST = new MultipleRecordAggregate(iAST, eAST, aAST, aggregatePos);
+ } else {
+ finish(aggregatePos);
+ aggregateAST = new SingleRecordAggregate(iAST, eAST, aggregatePos);
+ }
+ return aggregateAST;
+ }
+
+ ArrayAggregate parseArrayAggregate() throws SyntaxError {
+ ArrayAggregate aggregateAST = null; // in case there's a syntactic error
+
+ SourcePosition aggregatePos = new SourcePosition();
+ start(aggregatePos);
+
+ Expression eAST = parseExpression();
+ if (currentToken.kind == Token.COMMA) {
+ acceptIt();
+ ArrayAggregate aAST = parseArrayAggregate();
+ finish(aggregatePos);
+ aggregateAST = new MultipleArrayAggregate(eAST, aAST, aggregatePos);
+ } else {
+ finish(aggregatePos);
+ aggregateAST = new SingleArrayAggregate(eAST, aggregatePos);
+ }
+ return aggregateAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // VALUE-OR-VARIABLE NAMES
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ Vname parseVname() throws SyntaxError {
+ Vname vnameAST = null; // in case there's a syntactic error
+ Identifier iAST = parseIdentifier();
+ vnameAST = parseRestOfVname(iAST);
+ return vnameAST;
+ }
+
+ Vname parseRestOfVname(Identifier identifierAST) throws SyntaxError {
+ SourcePosition vnamePos = new SourcePosition();
+ vnamePos = identifierAST.getPosition();
+ Vname vAST = new SimpleVname(identifierAST, vnamePos);
+
+ while (currentToken.kind == Token.DOT || currentToken.kind == Token.LBRACKET) {
+
+ if (currentToken.kind == Token.DOT) {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ vAST = new DotVname(vAST, iAST, vnamePos);
+ } else {
+ acceptIt();
+ Expression eAST = parseExpression();
+ accept(Token.RBRACKET);
+ finish(vnamePos);
+ vAST = new SubscriptVname(vAST, eAST, vnamePos);
+ }
+ }
+ return vAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // DECLARATIONS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ Declaration parseDeclaration() throws SyntaxError {
+ Declaration declarationAST = null; // in case there's a syntactic error
+
+ SourcePosition declarationPos = new SourcePosition();
+ start(declarationPos);
+ declarationAST = parseSingleDeclaration();
+ while (currentToken.kind == Token.SEMICOLON) {
+ acceptIt();
+ Declaration d2AST = parseSingleDeclaration();
+ finish(declarationPos);
+ declarationAST = new SequentialDeclaration(declarationAST, d2AST, declarationPos);
+ }
+ return declarationAST;
+ }
+
+ Declaration parseSingleDeclaration() throws SyntaxError {
+ Declaration declarationAST = null; // in case there's a syntactic error
+
+ SourcePosition declarationPos = new SourcePosition();
+ start(declarationPos);
+
+ switch (currentToken.kind) {
+
+ case Token.CONST: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.IS);
+ Expression eAST = parseExpression();
+ finish(declarationPos);
+ declarationAST = new ConstDeclaration(iAST, eAST, declarationPos);
+ }
+ break;
+
+ case Token.VAR: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(declarationPos);
+ declarationAST = new VarDeclaration(iAST, tAST, declarationPos);
+ }
+ break;
+
+ case Token.PROC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.LPAREN);
+ FormalParameterSequence fpsAST = parseFormalParameterSequence();
+ accept(Token.RPAREN);
+ accept(Token.IS);
+ Command cAST = parseSingleCommand();
+ finish(declarationPos);
+ declarationAST = new ProcDeclaration(iAST, fpsAST, cAST, declarationPos);
+ }
+ break;
+
+ case Token.FUNC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.LPAREN);
+ FormalParameterSequence fpsAST = parseFormalParameterSequence();
+ accept(Token.RPAREN);
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ accept(Token.IS);
+ Expression eAST = parseExpression();
+ finish(declarationPos);
+ declarationAST = new FuncDeclaration(iAST, fpsAST, tAST, eAST, declarationPos);
+ }
+ break;
+
+ case Token.TYPE: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.IS);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(declarationPos);
+ declarationAST = new TypeDeclaration(iAST, tAST, declarationPos);
+ }
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start a declaration", currentToken.spelling);
+ break;
+
+ }
+ return declarationAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // PARAMETERS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ FormalParameterSequence parseFormalParameterSequence() throws SyntaxError {
+ FormalParameterSequence formalsAST;
+
+ SourcePosition formalsPos = new SourcePosition();
+
+ start(formalsPos);
+ if (currentToken.kind == Token.RPAREN) {
+ finish(formalsPos);
+ formalsAST = new EmptyFormalParameterSequence(formalsPos);
+
+ } else {
+ formalsAST = parseProperFormalParameterSequence();
+ }
+ return formalsAST;
+ }
+
+ FormalParameterSequence parseProperFormalParameterSequence() throws SyntaxError {
+ FormalParameterSequence formalsAST = null; // in case there's a syntactic error;
+
+ SourcePosition formalsPos = new SourcePosition();
+ start(formalsPos);
+ FormalParameter fpAST = parseFormalParameter();
+ if (currentToken.kind == Token.COMMA) {
+ acceptIt();
+ FormalParameterSequence fpsAST = parseProperFormalParameterSequence();
+ finish(formalsPos);
+ formalsAST = new MultipleFormalParameterSequence(fpAST, fpsAST, formalsPos);
+
+ } else {
+ finish(formalsPos);
+ formalsAST = new SingleFormalParameterSequence(fpAST, formalsPos);
+ }
+ return formalsAST;
+ }
+
+ FormalParameter parseFormalParameter() throws SyntaxError {
+ FormalParameter formalAST = null; // in case there's a syntactic error;
+
+ SourcePosition formalPos = new SourcePosition();
+ start(formalPos);
+
+ switch (currentToken.kind) {
+
+ case Token.IDENTIFIER: {
+ Identifier iAST = parseIdentifier();
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(formalPos);
+ formalAST = new ConstFormalParameter(iAST, tAST, formalPos);
+ }
+ break;
+
+ case Token.VAR: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(formalPos);
+ formalAST = new VarFormalParameter(iAST, tAST, formalPos);
+ }
+ break;
+
+ case Token.PROC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.LPAREN);
+ FormalParameterSequence fpsAST = parseFormalParameterSequence();
+ accept(Token.RPAREN);
+ finish(formalPos);
+ formalAST = new ProcFormalParameter(iAST, fpsAST, formalPos);
+ }
+ break;
+
+ case Token.FUNC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ accept(Token.LPAREN);
+ FormalParameterSequence fpsAST = parseFormalParameterSequence();
+ accept(Token.RPAREN);
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(formalPos);
+ formalAST = new FuncFormalParameter(iAST, fpsAST, tAST, formalPos);
+ }
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start a formal parameter", currentToken.spelling);
+ break;
+
+ }
+ return formalAST;
+ }
+
+ ActualParameterSequence parseActualParameterSequence() throws SyntaxError {
+ ActualParameterSequence actualsAST;
+
+ SourcePosition actualsPos = new SourcePosition();
+
+ start(actualsPos);
+ if (currentToken.kind == Token.RPAREN) {
+ finish(actualsPos);
+ actualsAST = new EmptyActualParameterSequence(actualsPos);
+
+ } else {
+ actualsAST = parseProperActualParameterSequence();
+ }
+ return actualsAST;
+ }
+
+ ActualParameterSequence parseProperActualParameterSequence() throws SyntaxError {
+ ActualParameterSequence actualsAST = null; // in case there's a syntactic error
+
+ SourcePosition actualsPos = new SourcePosition();
+
+ start(actualsPos);
+ ActualParameter apAST = parseActualParameter();
+ if (currentToken.kind == Token.COMMA) {
+ acceptIt();
+ ActualParameterSequence apsAST = parseProperActualParameterSequence();
+ finish(actualsPos);
+ actualsAST = new MultipleActualParameterSequence(apAST, apsAST, actualsPos);
+ } else {
+ finish(actualsPos);
+ actualsAST = new SingleActualParameterSequence(apAST, actualsPos);
+ }
+ return actualsAST;
+ }
+
+ ActualParameter parseActualParameter() throws SyntaxError {
+ ActualParameter actualAST = null; // in case there's a syntactic error
+
+ SourcePosition actualPos = new SourcePosition();
+
+ start(actualPos);
+
+ switch (currentToken.kind) {
+
+ case Token.IDENTIFIER:
+ case Token.INTLITERAL:
+ case Token.CHARLITERAL:
+ case Token.OPERATOR:
+ case Token.LET:
+ case Token.IF:
+ case Token.LPAREN:
+ case Token.LBRACKET:
+ case Token.LCURLY: {
+ Expression eAST = parseExpression();
+ finish(actualPos);
+ actualAST = new ConstActualParameter(eAST, actualPos);
+ }
+ break;
+
+ case Token.VAR: {
+ acceptIt();
+ Vname vAST = parseVname();
+ finish(actualPos);
+ actualAST = new VarActualParameter(vAST, actualPos);
+ }
+ break;
+
+ case Token.PROC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ finish(actualPos);
+ actualAST = new ProcActualParameter(iAST, actualPos);
+ }
+ break;
+
+ case Token.FUNC: {
+ acceptIt();
+ Identifier iAST = parseIdentifier();
+ finish(actualPos);
+ actualAST = new FuncActualParameter(iAST, actualPos);
+ }
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start an actual parameter", currentToken.spelling);
+ break;
+
+ }
+ return actualAST;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // TYPE-DENOTERS
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ TypeDenoter parseTypeDenoter() throws SyntaxError {
+ TypeDenoter typeAST = null; // in case there's a syntactic error
+ SourcePosition typePos = new SourcePosition();
+
+ start(typePos);
+
+ switch (currentToken.kind) {
+
+ case Token.IDENTIFIER: {
+ Identifier iAST = parseIdentifier();
+ finish(typePos);
+ typeAST = new SimpleTypeDenoter(iAST, typePos);
+ }
+ break;
+
+ case Token.ARRAY: {
+ acceptIt();
+ IntegerLiteral ilAST = parseIntegerLiteral();
+ accept(Token.OF);
+ TypeDenoter tAST = parseTypeDenoter();
+ finish(typePos);
+ typeAST = new ArrayTypeDenoter(ilAST, tAST, typePos);
+ }
+ break;
+
+ case Token.RECORD: {
+ acceptIt();
+ FieldTypeDenoter fAST = parseFieldTypeDenoter();
+ accept(Token.END);
+ finish(typePos);
+ typeAST = new RecordTypeDenoter(fAST, typePos);
+ }
+ break;
+
+ default:
+ syntacticError("\"%\" cannot start a type denoter", currentToken.spelling);
+ break;
+
+ }
+ return typeAST;
+ }
+
+ FieldTypeDenoter parseFieldTypeDenoter() throws SyntaxError {
+ FieldTypeDenoter fieldAST = null; // in case there's a syntactic error
+
+ SourcePosition fieldPos = new SourcePosition();
+
+ start(fieldPos);
+ Identifier iAST = parseIdentifier();
+ accept(Token.COLON);
+ TypeDenoter tAST = parseTypeDenoter();
+ if (currentToken.kind == Token.COMMA) {
+ acceptIt();
+ FieldTypeDenoter fAST = parseFieldTypeDenoter();
+ finish(fieldPos);
+ fieldAST = new MultipleFieldTypeDenoter(iAST, tAST, fAST, fieldPos);
+ } else {
+ finish(fieldPos);
+ fieldAST = new SingleFieldTypeDenoter(iAST, tAST, fieldPos);
+ }
+ return fieldAST;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java
new file mode 100644
index 0000000..4da5ed5
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java
@@ -0,0 +1,272 @@
+/*
+ * @(#)Scanner.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+public final class Scanner {
+
+ private SourceFile sourceFile;
+ private boolean debug;
+
+ private char currentChar;
+ private StringBuffer currentSpelling;
+ private boolean currentlyScanningToken;
+
+ private boolean isLetter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+ private boolean isDigit(char c) {
+ return (c >= '0' && c <= '9');
+ }
+
+ // isOperator returns true iff the given character is an operator character.
+
+ private boolean isOperator(char c) {
+ return (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '<' || c == '>' || c == '\\'
+ || c == '&' || c == '@' || c == '%' || c == '^' || c == '?');
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ public Scanner(SourceFile source) {
+ sourceFile = source;
+ currentChar = sourceFile.getSource();
+ debug = false;
+ }
+
+ public void enableDebugging() {
+ debug = true;
+ }
+
+ // takeIt appends the current character to the current token, and gets
+ // the next character from the source program.
+
+ private void takeIt() {
+ if (currentlyScanningToken)
+ currentSpelling.append(currentChar);
+ currentChar = sourceFile.getSource();
+ }
+
+ // scanSeparator skips a single separator.
+
+ private void scanSeparator() {
+ switch (currentChar) {
+
+ // comment
+ case '!': {
+ takeIt();
+ while ((currentChar != SourceFile.EOL) && (currentChar != SourceFile.EOT))
+ takeIt();
+ if (currentChar == SourceFile.EOL)
+ takeIt();
+ }
+ break;
+
+ // whitespace
+ case ' ':
+ case '\n':
+ case '\r':
+ case '\t':
+ takeIt();
+ break;
+ }
+ }
+
+ private int scanToken() {
+
+ switch (currentChar) {
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ takeIt();
+ while (isLetter(currentChar) || isDigit(currentChar))
+ takeIt();
+ return Token.IDENTIFIER;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ takeIt();
+ while (isDigit(currentChar))
+ takeIt();
+ return Token.INTLITERAL;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '=':
+ case '<':
+ case '>':
+ case '\\':
+ case '&':
+ case '@':
+ case '%':
+ case '^':
+ case '?':
+ takeIt();
+ while (isOperator(currentChar))
+ takeIt();
+ return Token.OPERATOR;
+
+ case '\'':
+ takeIt();
+ takeIt(); // the quoted character
+ if (currentChar == '\'') {
+ takeIt();
+ return Token.CHARLITERAL;
+ } else
+ return Token.ERROR;
+
+ case '.':
+ takeIt();
+ return Token.DOT;
+
+ case ':':
+ takeIt();
+ if (currentChar == '=') {
+ takeIt();
+ return Token.BECOMES;
+ } else
+ return Token.COLON;
+
+ case ';':
+ takeIt();
+ return Token.SEMICOLON;
+
+ case ',':
+ takeIt();
+ return Token.COMMA;
+
+ case '~':
+ takeIt();
+ return Token.IS;
+
+ case '(':
+ takeIt();
+ return Token.LPAREN;
+
+ case ')':
+ takeIt();
+ return Token.RPAREN;
+
+ case '[':
+ takeIt();
+ return Token.LBRACKET;
+
+ case ']':
+ takeIt();
+ return Token.RBRACKET;
+
+ case '{':
+ takeIt();
+ return Token.LCURLY;
+
+ case '}':
+ takeIt();
+ return Token.RCURLY;
+
+ case SourceFile.EOT:
+ return Token.EOT;
+
+ default:
+ takeIt();
+ return Token.ERROR;
+ }
+ }
+
+ public Token scan() {
+ Token tok;
+ SourcePosition pos;
+ int kind;
+
+ currentlyScanningToken = false;
+ // skip any whitespace or comments
+ while (currentChar == '!' || currentChar == ' ' || currentChar == '\n' || currentChar == '\r'
+ || currentChar == '\t')
+ scanSeparator();
+
+ currentlyScanningToken = true;
+ currentSpelling = new StringBuffer("");
+ pos = new SourcePosition();
+ pos.start = sourceFile.getCurrentLine();
+
+ kind = scanToken();
+
+ pos.finish = sourceFile.getCurrentLine();
+ tok = new Token(kind, currentSpelling.toString(), pos);
+ if (debug)
+ System.out.println(tok);
+ return tok;
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java
new file mode 100644
index 0000000..3651455
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java
@@ -0,0 +1,68 @@
+/*
+ * @(#)SourceFile.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+import java.net.URL;
+
+public class SourceFile {
+
+ public static final char EOL = '\n';
+ public static final char EOT = '\u0000';
+
+ java.io.File sourceFile;
+ java.io.InputStream source;
+ int currentLine;
+
+ public static SourceFile ofPath(String pathname) {
+ try {
+ SourceFile sf = new SourceFile();
+ sf.sourceFile = new java.io.File(pathname);
+ sf.source = new java.io.FileInputStream(sf.sourceFile);
+ return sf;
+ } catch (java.io.IOException s) {
+ return null;
+ }
+ }
+
+ public static SourceFile fromResource(String handle) {
+ SourceFile sf = new SourceFile();
+ //sf.sourceFile = new java.io.File(pathname);
+ sf.source = sf.getClass().getResourceAsStream(handle);
+ return sf;
+ }
+
+ private SourceFile() {
+ currentLine = 1;
+ }
+
+ char getSource() {
+ try {
+ int c = source.read();
+
+ if (c == -1) {
+ c = EOT;
+ } else if (c == EOL) {
+ currentLine++;
+ }
+ return (char) c;
+ } catch (java.io.IOException s) {
+ return EOT;
+ }
+ }
+
+ int getCurrentLine() {
+ return currentLine;
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java
new file mode 100644
index 0000000..fbd5716
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java
@@ -0,0 +1,35 @@
+/*
+ * @(#)SourcePosition.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+public class SourcePosition {
+
+ public int start, finish;
+
+ public SourcePosition() {
+ start = 0;
+ finish = 0;
+ }
+
+ public SourcePosition(int s, int f) {
+ start = s;
+ finish = f;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + start + ", " + finish + ")";
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java
new file mode 100644
index 0000000..1ea031d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)SyntaxError.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+class SyntaxError extends Exception {
+
+ private static final long serialVersionUID = -5280306336102766860L;
+
+ SyntaxError() {
+ super();
+ }
+
+ SyntaxError(String s) {
+ super(s);
+ }
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java
new file mode 100644
index 0000000..51f3203
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java
@@ -0,0 +1,84 @@
+/*
+ * @(#)Token.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.syntacticAnalyzer;
+
+final class Token extends Object {
+
+ protected int kind;
+ protected String spelling;
+ protected SourcePosition position;
+
+ public Token(int kind, String spelling, SourcePosition position) {
+
+ if (kind == Token.IDENTIFIER) {
+ int currentKind = firstReservedWord;
+ boolean searching = true;
+
+ while (searching) {
+ int comparison = tokenTable[currentKind].compareTo(spelling);
+ if (comparison == 0) {
+ this.kind = currentKind;
+ searching = false;
+ } else if (comparison > 0 || currentKind == lastReservedWord) {
+ this.kind = Token.IDENTIFIER;
+ searching = false;
+ } else {
+ currentKind++;
+ }
+ }
+ } else
+ this.kind = kind;
+
+ this.spelling = spelling;
+ this.position = position;
+
+ }
+
+ public static String spell(int kind) {
+ return tokenTable[kind];
+ }
+
+ @Override
+ public String toString() {
+ return "Kind=" + kind + ", spelling=" + spelling + ", position=" + position;
+ }
+
+ // Token classes...
+
+ public static final int
+
+ // literals, identifiers, operators...
+ INTLITERAL = 0, CHARLITERAL = 1, IDENTIFIER = 2, OPERATOR = 3,
+
+ // reserved words - must be in alphabetical order...
+ ARRAY = 4, BEGIN = 5, CONST = 6, DO = 7, ELSE = 8, END = 9, FUNC = 10, IF = 11, IN = 12, LET = 13, OF = 14,
+ PROC = 15, RECORD = 16, THEN = 17, TYPE = 18, VAR = 19, WHILE = 20,
+
+ // punctuation...
+ DOT = 21, COLON = 22, SEMICOLON = 23, COMMA = 24, BECOMES = 25, IS = 26,
+
+ // brackets...
+ LPAREN = 27, RPAREN = 28, LBRACKET = 29, RBRACKET = 30, LCURLY = 31, RCURLY = 32,
+
+ // special tokens...
+ EOT = 33, ERROR = 34;
+
+ private static String[] tokenTable = new String[] { "", "", "", "", "array",
+ "begin", "const", "do", "else", "end", "func", "if", "in", "let", "of", "proc", "record", "then", "type",
+ "var", "while", ".", ":", ";", ",", ":=", "~", "(", ")", "[", "]", "{", "}", "", "" };
+
+ private final static int firstReservedWord = Token.ARRAY, lastReservedWord = Token.WHILE;
+
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java
new file mode 100644
index 0000000..53fd82f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java
@@ -0,0 +1,68 @@
+/*
+ * @(#)Drawer.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Point;
+
+import triangle.abstractSyntaxTrees.Program;
+
+public class Drawer {
+
+ private DrawerFrame frame;
+ private DrawerPanel panel;
+
+ private Program theAST;
+ private DrawingTree theDrawing;
+
+ // Draw the AST representing a complete program.
+
+ public void draw(Program ast) {
+ theAST = ast;
+ panel = new DrawerPanel(this);
+ frame = new DrawerFrame(panel);
+
+ Font font = new Font("SansSerif", Font.PLAIN, 12);
+ frame.setFont(font);
+
+ FontMetrics fontMetrics = frame.getFontMetrics(font);
+
+ // another class of visitor is used for drawing the tree: LayoutVisitor
+ // LayoutVisitor is passed to the AST which, in turn, calls visitProgram
+ // and then each AST node is visited. This ultimately constructs a
+ // DrawingTree, which is structurally the same as the AST but is decorated
+ // with coordinates (and has only DrawingTree objects as nodes)
+ // Each DrawingTree object knows how to paint itself, so it's passed to a
+ // DrawerPanel and DrawerFrame for display
+ LayoutVisitor layout = new LayoutVisitor(fontMetrics);
+ theDrawing = (DrawingTree) theAST.visit(layout, null);
+ theDrawing.position(new Point(2048, 10));
+
+ frame.setVisible(true);
+ }
+
+ public void paintAST(Graphics g) {
+ g.setColor(panel.getBackground());
+ Dimension d = panel.getSize();
+ g.fillRect(0, 0, d.width, d.height);
+
+ if (theDrawing != null) {
+ theDrawing.paint(g);
+ }
+ }
+}
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java
new file mode 100644
index 0000000..a939c44
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java
@@ -0,0 +1,74 @@
+/*
+ * @(#)DrawerFrame.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
+class DrawerFrame extends JFrame {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3650404598416929282L;
+
+ public DrawerFrame(JPanel panel) {
+ setSize(300, 200);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ Dimension d = tk.getScreenSize();
+ int screenHeight = d.height;
+ int screenWidth = d.width;
+ setTitle("Triangle Compiler Abstract Syntax Tree");
+ setSize(screenWidth / 2, screenHeight / 2);
+ setLocation(screenWidth / 4, screenHeight / 4);
+ // Image img = tk.getImage("icon.gif");
+ // setIconImage(img);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+ Container contentPane = getContentPane();
+ final JScrollPane jScrollPane = new JScrollPane(panel);
+
+ contentPane.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ super.componentResized(e);
+ jScrollPane.getHorizontalScrollBar().setValue(jScrollPane.getHorizontalScrollBar().getMaximum());
+ jScrollPane.getHorizontalScrollBar().setValue(jScrollPane.getHorizontalScrollBar().getValue() / 2);
+ }
+ });
+
+ contentPane.add(jScrollPane);
+
+ }
+
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java
new file mode 100644
index 0000000..40c3b72
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)DrawerPanel.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+
+import javax.swing.JPanel;
+
+class DrawerPanel extends JPanel {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 565914745506889669L;
+ private Drawer drawer;
+
+ public DrawerPanel(Drawer drawer) {
+ setPreferredSize(new Dimension(4096, 4096));
+ this.drawer = drawer;
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ drawer.paintAST(g);
+ }
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java
new file mode 100644
index 0000000..742eb6f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java
@@ -0,0 +1,84 @@
+/*
+ * @(#)DrawingTree.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Point;
+
+public class DrawingTree {
+
+ String caption;
+ int width, height;
+ Point pos, offset;
+ Polygon contour;
+ DrawingTree parent;
+ DrawingTree[] children;
+
+ public DrawingTree(String caption, int width, int height) {
+ this.caption = caption;
+ this.width = width;
+ this.height = height;
+ this.parent = null;
+ this.children = null;
+ this.pos = new Point(0, 0);
+ this.offset = new Point(0, 0);
+ this.contour = new Polygon();
+ }
+
+ public void setChildren(DrawingTree[] children) {
+ this.children = children;
+ for (int i = 0; i < children.length; i++)
+ children[i].parent = this;
+ }
+
+ private final int FIXED_FONT_HEIGHT = 10;
+ private final Color nodeColor = new Color(250, 220, 100);
+
+ public void paint(Graphics graphics) {
+ graphics.setColor(nodeColor);
+ graphics.fillRect(pos.x, pos.y, width, height);
+ graphics.setColor(Color.black);
+ graphics.drawRect(pos.x, pos.y, width - 1, height - 1);
+ graphics.drawString(caption, pos.x + 2, pos.y + (height + FIXED_FONT_HEIGHT) / 2);
+
+ if (children != null) {
+ for (DrawingTree child : children) {
+ child.paint(graphics);
+ }
+ }
+
+ if (parent != null) {
+ graphics.drawLine(pos.x + width / 2, pos.y, parent.pos.x + parent.width / 2, parent.pos.y + parent.height);
+ }
+ }
+
+ public void position(Point pos) {
+
+ this.pos.x = pos.x + this.offset.x;
+ this.pos.y = pos.y + this.offset.y;
+
+ Point temp = new Point(this.pos.x, this.pos.y);
+
+ if (children != null) {
+ for (DrawingTree child : children) {
+ child.position(temp);
+ temp.x += child.offset.x;
+ temp.y = this.pos.y + children[0].offset.y;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java
new file mode 100644
index 0000000..dfa4b35
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java
@@ -0,0 +1,680 @@
+/*
+ * @(#)LayoutVisitor.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+import java.awt.FontMetrics;
+
+import triangle.abstractSyntaxTrees.Program;
+import triangle.abstractSyntaxTrees.actuals.ConstActualParameter;
+import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.FuncActualParameter;
+import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.ProcActualParameter;
+import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence;
+import triangle.abstractSyntaxTrees.actuals.VarActualParameter;
+import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate;
+import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate;
+import triangle.abstractSyntaxTrees.commands.AssignCommand;
+import triangle.abstractSyntaxTrees.commands.CallCommand;
+import triangle.abstractSyntaxTrees.commands.EmptyCommand;
+import triangle.abstractSyntaxTrees.commands.IfCommand;
+import triangle.abstractSyntaxTrees.commands.LetCommand;
+import triangle.abstractSyntaxTrees.commands.SequentialCommand;
+import triangle.abstractSyntaxTrees.commands.WhileCommand;
+import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ConstDeclaration;
+import triangle.abstractSyntaxTrees.declarations.FuncDeclaration;
+import triangle.abstractSyntaxTrees.declarations.ProcDeclaration;
+import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration;
+import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration;
+import triangle.abstractSyntaxTrees.declarations.VarDeclaration;
+import triangle.abstractSyntaxTrees.expressions.ArrayExpression;
+import triangle.abstractSyntaxTrees.expressions.BinaryExpression;
+import triangle.abstractSyntaxTrees.expressions.CallExpression;
+import triangle.abstractSyntaxTrees.expressions.CharacterExpression;
+import triangle.abstractSyntaxTrees.expressions.EmptyExpression;
+import triangle.abstractSyntaxTrees.expressions.IfExpression;
+import triangle.abstractSyntaxTrees.expressions.IntegerExpression;
+import triangle.abstractSyntaxTrees.expressions.LetExpression;
+import triangle.abstractSyntaxTrees.expressions.RecordExpression;
+import triangle.abstractSyntaxTrees.expressions.UnaryExpression;
+import triangle.abstractSyntaxTrees.expressions.VnameExpression;
+import triangle.abstractSyntaxTrees.formals.ConstFormalParameter;
+import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.FuncFormalParameter;
+import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.ProcFormalParameter;
+import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence;
+import triangle.abstractSyntaxTrees.formals.VarFormalParameter;
+import triangle.abstractSyntaxTrees.terminals.CharacterLiteral;
+import triangle.abstractSyntaxTrees.terminals.Identifier;
+import triangle.abstractSyntaxTrees.terminals.IntegerLiteral;
+import triangle.abstractSyntaxTrees.terminals.Operator;
+import triangle.abstractSyntaxTrees.types.AnyTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter;
+import triangle.abstractSyntaxTrees.types.BoolTypeDenoter;
+import triangle.abstractSyntaxTrees.types.CharTypeDenoter;
+import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter;
+import triangle.abstractSyntaxTrees.types.IntTypeDenoter;
+import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.RecordTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter;
+import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter;
+import triangle.abstractSyntaxTrees.types.TypeDeclaration;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor;
+import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.CommandVisitor;
+import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor;
+import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor;
+import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor;
+import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor;
+import triangle.abstractSyntaxTrees.visitors.LiteralVisitor;
+import triangle.abstractSyntaxTrees.visitors.OperatorVisitor;
+import triangle.abstractSyntaxTrees.visitors.ProgramVisitor;
+import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor;
+import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor;
+import triangle.abstractSyntaxTrees.visitors.VnameVisitor;
+import triangle.abstractSyntaxTrees.vnames.DotVname;
+import triangle.abstractSyntaxTrees.vnames.SimpleVname;
+import triangle.abstractSyntaxTrees.vnames.SubscriptVname;
+
+public class LayoutVisitor implements ActualParameterVisitor,
+ ActualParameterSequenceVisitor, ArrayAggregateVisitor,
+ CommandVisitor, DeclarationVisitor, ExpressionVisitor,
+ FormalParameterSequenceVisitor, IdentifierVisitor,
+ LiteralVisitor, OperatorVisitor, ProgramVisitor,
+ RecordAggregateVisitor, TypeDenoterVisitor,
+ VnameVisitor {
+
+ private final int BORDER = 5;
+ private final int PARENT_SEP = 30;
+
+ private FontMetrics fontMetrics;
+
+ public LayoutVisitor(FontMetrics fontMetrics) {
+ this.fontMetrics = fontMetrics;
+ }
+
+ // Commands
+ @Override
+ public DrawingTree visitAssignCommand(AssignCommand ast, Void obj) {
+ var d1 = ast.V.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("AssignCom.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitCallCommand(CallCommand ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.APS.visit(this);
+ return layoutBinary("CallCom.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitEmptyCommand(EmptyCommand ast, Void obj) {
+ return layoutNullary("EmptyCom.");
+ }
+
+ @Override
+ public DrawingTree visitIfCommand(IfCommand ast, Void obj) {
+ var d1 = ast.E.visit(this);
+ var d2 = ast.C1.visit(this);
+ var d3 = ast.C2.visit(this);
+ return layoutTernary("IfCom.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitLetCommand(LetCommand ast, Void obj) {
+ var d1 = ast.D.visit(this);
+ var d2 = ast.C.visit(this);
+ return layoutBinary("LetCom.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitSequentialCommand(SequentialCommand ast, Void obj) {
+ var d1 = ast.C1.visit(this);
+ var d2 = ast.C2.visit(this);
+ return layoutBinary("Seq.Com.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitWhileCommand(WhileCommand ast, Void obj) {
+ var d1 = ast.E.visit(this);
+ var d2 = ast.C.visit(this);
+ return layoutBinary("WhileCom.", d1, d2);
+ }
+
+ // Expressions
+ @Override
+ public DrawingTree visitArrayExpression(ArrayExpression ast, Void obj) {
+ var d1 = ast.AA.visit(this);
+ return layoutUnary("ArrayExpr.", d1);
+ }
+
+ @Override
+ public DrawingTree visitBinaryExpression(BinaryExpression ast, Void obj) {
+ var d1 = ast.E1.visit(this);
+ var d2 = ast.O.visit(this);
+ var d3 = ast.E2.visit(this);
+ return layoutTernary("Bin.Expr.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitCallExpression(CallExpression ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.APS.visit(this);
+ return layoutBinary("CallExpr.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitCharacterExpression(CharacterExpression ast, Void obj) {
+ var d1 = ast.CL.visit(this);
+ return layoutUnary("Char.Expr.", d1);
+ }
+
+ @Override
+ public DrawingTree visitEmptyExpression(EmptyExpression ast, Void obj) {
+ return layoutNullary("EmptyExpr.");
+ }
+
+ @Override
+ public DrawingTree visitIfExpression(IfExpression ast, Void obj) {
+ var d1 = ast.E1.visit(this);
+ var d2 = ast.E2.visit(this);
+ var d3 = ast.E3.visit(this);
+ return layoutTernary("IfExpr.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitIntegerExpression(IntegerExpression ast, Void obj) {
+ var d1 = ast.IL.visit(this);
+ return layoutUnary("Int.Expr.", d1);
+ }
+
+ @Override
+ public DrawingTree visitLetExpression(LetExpression ast, Void obj) {
+ var d1 = ast.D.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("LetExpr.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitRecordExpression(RecordExpression ast, Void obj) {
+ var d1 = ast.RA.visit(this);
+ return layoutUnary("Rec.Expr.", d1);
+ }
+
+ @Override
+ public DrawingTree visitUnaryExpression(UnaryExpression ast, Void obj) {
+ var d1 = ast.O.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("UnaryExpr.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitVnameExpression(VnameExpression ast, Void obj) {
+ var d1 = ast.V.visit(this);
+ return layoutUnary("VnameExpr.", d1);
+ }
+
+ // Declarations
+ @Override
+ public DrawingTree visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void obj) {
+ var d1 = ast.O.visit(this);
+ var d2 = ast.ARG1.visit(this);
+ var d3 = ast.ARG2.visit(this);
+ var d4 = ast.RES.visit(this);
+ return layoutQuaternary("Bin.Op.Decl.", d1, d2, d3, d4);
+ }
+
+ @Override
+ public DrawingTree visitConstDeclaration(ConstDeclaration ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("ConstDecl.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitFuncDeclaration(FuncDeclaration ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.FPS.visit(this);
+ var d3 = ast.T.visit(this);
+ var d4 = ast.E.visit(this);
+ return layoutQuaternary("FuncDecl.", d1, d2, d3, d4);
+ }
+
+ @Override
+ public DrawingTree visitProcDeclaration(ProcDeclaration ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.FPS.visit(this);
+ var d3 = ast.C.visit(this);
+ return layoutTernary("ProcDecl.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitSequentialDeclaration(SequentialDeclaration ast, Void obj) {
+ var d1 = ast.D1.visit(this);
+ var d2 = ast.D2.visit(this);
+ return layoutBinary("Seq.Decl.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitTypeDeclaration(TypeDeclaration ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("TypeDecl.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void obj) {
+ var d1 = ast.O.visit(this);
+ var d2 = ast.ARG.visit(this);
+ var d3 = ast.RES.visit(this);
+ return layoutTernary("UnaryOp.Decl.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitVarDeclaration(VarDeclaration ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("VarDecl.", d1, d2);
+ }
+
+ // Array Aggregates
+ @Override
+ public DrawingTree visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void obj) {
+ var d1 = ast.E.visit(this);
+ var d2 = ast.AA.visit(this);
+ return layoutBinary("Mult.ArrayAgg.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitSingleArrayAggregate(SingleArrayAggregate ast, Void obj) {
+ var d1 = ast.E.visit(this);
+ return layoutUnary("Sing.ArrayAgg.", d1);
+ }
+
+ // Record Aggregates
+ @Override
+ public DrawingTree visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.E.visit(this);
+ var d3 = ast.RA.visit(this);
+ return layoutTernary("Mult.Rec.Agg.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitSingleRecordAggregate(SingleRecordAggregate ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("Sing.Rec.Agg.", d1, d2);
+ }
+
+ // Formal Parameters
+ @Override
+ public DrawingTree visitConstFormalParameter(ConstFormalParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("ConstF.P.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitFuncFormalParameter(FuncFormalParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.FPS.visit(this);
+ var d3 = ast.T.visit(this);
+ return layoutTernary("FuncF.P.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitProcFormalParameter(ProcFormalParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.FPS.visit(this);
+ return layoutBinary("ProcF.P.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitVarFormalParameter(VarFormalParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("VarF.P.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void obj) {
+ return layoutNullary("EmptyF.P.S.");
+ }
+
+ @Override
+ public DrawingTree visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void obj) {
+ var d1 = ast.FP.visit(this);
+ var d2 = ast.FPS.visit(this);
+ return layoutBinary("Mult.F.P.S.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void obj) {
+ var d1 = ast.FP.visit(this);
+ return layoutUnary("Sing.F.P.S.", d1);
+ }
+
+ // Actual Parameters
+ @Override
+ public DrawingTree visitConstActualParameter(ConstActualParameter ast, Void obj) {
+ var d1 = ast.E.visit(this);
+ return layoutUnary("ConstA.P.", d1);
+ }
+
+ @Override
+ public DrawingTree visitFuncActualParameter(FuncActualParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ return layoutUnary("FuncA.P.", d1);
+ }
+
+ @Override
+ public DrawingTree visitProcActualParameter(ProcActualParameter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ return layoutUnary("ProcA.P.", d1);
+ }
+
+ @Override
+ public DrawingTree visitVarActualParameter(VarActualParameter ast, Void obj) {
+ var d1 = ast.V.visit(this);
+ return layoutUnary("VarA.P.", d1);
+ }
+
+ @Override
+ public DrawingTree visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Void obj) {
+ return layoutNullary("EmptyA.P.S.");
+ }
+
+ @Override
+ public DrawingTree visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Void obj) {
+ var d1 = ast.AP.visit(this);
+ var d2 = ast.APS.visit(this);
+ return layoutBinary("Mult.A.P.S.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitSingleActualParameterSequence(SingleActualParameterSequence ast, Void obj) {
+ var d1 = ast.AP.visit(this);
+ return layoutUnary("Sing.A.P.S.", d1);
+ }
+
+ // Type Denoters
+ @Override
+ public DrawingTree visitAnyTypeDenoter(AnyTypeDenoter ast, Void obj) {
+ return layoutNullary("any");
+ }
+
+ @Override
+ public DrawingTree visitArrayTypeDenoter(ArrayTypeDenoter ast, Void obj) {
+ var d1 = ast.IL.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("ArrayTypeD.", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitBoolTypeDenoter(BoolTypeDenoter ast, Void obj) {
+ return layoutNullary("bool");
+ }
+
+ @Override
+ public DrawingTree visitCharTypeDenoter(CharTypeDenoter ast, Void obj) {
+ return layoutNullary("char");
+ }
+
+ @Override
+ public DrawingTree visitErrorTypeDenoter(ErrorTypeDenoter ast, Void obj) {
+ return layoutNullary("error");
+ }
+
+ @Override
+ public DrawingTree visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ return layoutUnary("Sim.TypeD.", d1);
+ }
+
+ @Override
+ public DrawingTree visitIntTypeDenoter(IntTypeDenoter ast, Void obj) {
+ return layoutNullary("int");
+ }
+
+ @Override
+ public DrawingTree visitRecordTypeDenoter(RecordTypeDenoter ast, Void obj) {
+ var d1 = ast.FT.visit(this);
+ return layoutUnary("Rec.TypeD.", d1);
+ }
+
+ @Override
+ public DrawingTree visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ var d3 = ast.FT.visit(this);
+ return layoutTernary("Mult.F.TypeD.", d1, d2, d3);
+ }
+
+ @Override
+ public DrawingTree visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.T.visit(this);
+ return layoutBinary("Sing.F.TypeD.", d1, d2);
+ }
+
+ // Literals, Identifiers and Operators
+ @Override
+ public DrawingTree visitCharacterLiteral(CharacterLiteral ast, Void obj) {
+ return layoutNullary(ast.spelling);
+ }
+
+ @Override
+ public DrawingTree visitIdentifier(Identifier ast, Void obj) {
+ return layoutNullary(ast.spelling);
+ }
+
+ @Override
+ public DrawingTree visitIntegerLiteral(IntegerLiteral ast, Void obj) {
+ return layoutNullary(ast.spelling);
+ }
+
+ @Override
+ public DrawingTree visitOperator(Operator ast, Void obj) {
+ return layoutNullary(ast.spelling);
+ }
+
+ // Value-or-variable names
+ @Override
+ public DrawingTree visitDotVname(DotVname ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ var d2 = ast.V.visit(this);
+ return layoutBinary("DotVname", d1, d2);
+ }
+
+ @Override
+ public DrawingTree visitSimpleVname(SimpleVname ast, Void obj) {
+ var d1 = ast.I.visit(this);
+ return layoutUnary("Sim.Vname", d1);
+ }
+
+ @Override
+ public DrawingTree visitSubscriptVname(SubscriptVname ast, Void obj) {
+ var d1 = ast.V.visit(this);
+ var d2 = ast.E.visit(this);
+ return layoutBinary("Sub.Vname", d1, d2);
+ }
+
+ // Programs
+ @Override
+ public DrawingTree visitProgram(Program ast, Void obj) {
+ var d1 = ast.C.visit(this);
+ return layoutUnary("Program", d1);
+ }
+
+ private DrawingTree layoutCaption(String name) {
+ var w = fontMetrics.stringWidth(name) + 4;
+ var h = fontMetrics.getHeight() + 4;
+ return new DrawingTree(name, w, h);
+ }
+
+ private DrawingTree layoutNullary(String name) {
+ var dt = layoutCaption(name);
+ dt.contour.upper_tail = new Polyline(0, dt.height + 2 * BORDER, null);
+ dt.contour.upper_head = dt.contour.upper_tail;
+ dt.contour.lower_tail = new Polyline(-dt.width - 2 * BORDER, 0, null);
+ dt.contour.lower_head = new Polyline(0, dt.height + 2 * BORDER, dt.contour.lower_tail);
+ return dt;
+ }
+
+ private DrawingTree layoutUnary(String name, DrawingTree d1) {
+ var dt = layoutCaption(name);
+ dt.setChildren(new DrawingTree[] { d1 });
+ attachParent(dt, join(dt));
+ return dt;
+ }
+
+ private DrawingTree layoutBinary(String name, DrawingTree d1, DrawingTree d2) {
+ var dt = layoutCaption(name);
+ dt.setChildren(new DrawingTree[] { d1, d2 });
+ attachParent(dt, join(dt));
+ return dt;
+ }
+
+ private DrawingTree layoutTernary(String name, DrawingTree d1, DrawingTree d2, DrawingTree d3) {
+ var dt = layoutCaption(name);
+ dt.setChildren(new DrawingTree[] { d1, d2, d3 });
+ attachParent(dt, join(dt));
+ return dt;
+ }
+
+ private DrawingTree layoutQuaternary(String name, DrawingTree d1, DrawingTree d2, DrawingTree d3, DrawingTree d4) {
+ var dt = layoutCaption(name);
+ dt.setChildren(new DrawingTree[] { d1, d2, d3, d4 });
+ attachParent(dt, join(dt));
+ return dt;
+ }
+
+ private void attachParent(DrawingTree dt, int w) {
+ var y = PARENT_SEP;
+ var x2 = (w - dt.width) / 2 - BORDER;
+ var x1 = x2 + dt.width + 2 * BORDER - w;
+
+ dt.children[0].offset.y = y + dt.height;
+ dt.children[0].offset.x = x1;
+ dt.contour.upper_head = new Polyline(0, dt.height, new Polyline(x1, y, dt.contour.upper_head));
+ dt.contour.lower_head = new Polyline(0, dt.height, new Polyline(x2, y, dt.contour.lower_head));
+ }
+
+ private int join(DrawingTree dt) {
+
+ dt.contour = dt.children[0].contour;
+ var sum = dt.children[0].width + 2 * BORDER;
+ var w = sum;
+
+ for (var i = 1; i < dt.children.length; i++) {
+ var d = merge(dt.contour, dt.children[i].contour);
+ dt.children[i].offset.x = d + w;
+ dt.children[i].offset.y = 0;
+ w = dt.children[i].width + 2 * BORDER;
+ sum += d + w;
+ }
+ return sum;
+ }
+
+ private int merge(Polygon c1, Polygon c2) {
+ int x = 0, y = 0, total = 0;
+ var upper = c1.lower_head;
+ var lower = c2.upper_head;
+
+ while (lower != null && upper != null) {
+ var d = offset(x, y, lower.dx, lower.dy, upper.dx, upper.dy);
+ x += d;
+ total += d;
+
+ if (y + lower.dy <= upper.dy) {
+ x += lower.dx;
+ y += lower.dy;
+ lower = lower.link;
+ } else {
+ x -= upper.dx;
+ y -= upper.dy;
+ upper = upper.link;
+ }
+ }
+
+ if (lower != null) {
+ var b = bridge(c1.upper_tail, 0, 0, lower, x, y);
+ c1.upper_tail = (b.link != null) ? c2.upper_tail : b;
+ c1.lower_tail = c2.lower_tail;
+ } else {
+ var b = bridge(c2.lower_tail, x, y, upper, 0, 0);
+ if (b.link == null) {
+ c1.lower_tail = b;
+ }
+ }
+
+ c1.lower_head = c2.lower_head;
+
+ return total;
+ }
+
+ private int offset(int p1, int p2, int a1, int a2, int b1, int b2) {
+
+ if (b2 <= p2 || p2 + a2 <= 0) {
+ return 0;
+ }
+
+ var t = b2 * a1 - a2 * b1;
+ if (t > 0) {
+ if (p2 < 0) {
+ var s = p2 * a1;
+ return Math.max(0, s / a2 - p1);
+ } else if (p2 > 0) {
+ var s = p2 * b1;
+ return Math.max(0, s / b2 - p1);
+ } else {
+ return Math.max(0, -p1);
+ }
+ } else if (b2 < p2 + a2) {
+ var s = (b2 - p2) * a1;
+ return Math.max(0, b1 - (p1 + s / a2));
+ } else if (b2 > p2 + a2) {
+ var s = (a2 + p2) * b1;
+ return Math.max(0, s / b2 - (p1 + a1));
+ } else {
+ return Math.max(0, b1 - (p1 + a1));
+ }
+ }
+
+ private Polyline bridge(Polyline line1, int x1, int y1, Polyline line2, int x2, int y2) {
+
+ int dx;
+ var dy = y2 + line2.dy - y1;
+ if (line2.dy == 0) {
+ dx = line2.dx;
+ } else {
+ var s = dy * line2.dx;
+ dx = s / line2.dy;
+ }
+
+ var r = new Polyline(dx, dy, line2.link);
+ line1.link = new Polyline(x2 + line2.dx - dx - x1, 0, r);
+
+ return r;
+ }
+
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java
new file mode 100644
index 0000000..d9bd6d0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java
@@ -0,0 +1,20 @@
+/*
+ * @(#)Polygon.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+class Polygon {
+ Polyline lower_head, lower_tail;
+ Polyline upper_head, upper_tail;
+}
\ No newline at end of file
diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java
new file mode 100644
index 0000000..546c37f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java
@@ -0,0 +1,29 @@
+/*
+ * @(#)Polyline.java 2.1 2003/10/07
+ *
+ * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown
+ * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland
+ * and School of Computer and Math Sciences, The Robert Gordon University,
+ * St. Andrew Street, Aberdeen AB25 1HG, Scotland.
+ * All rights reserved.
+ *
+ * This software is provided free for educational use only. It may
+ * not be used for commercial purposes without the prior written permission
+ * of the authors.
+ */
+
+package triangle.treeDrawer;
+
+/**
+ * used to keep track of the position for components in the tree to be drawn
+ */
+class Polyline {
+ int dx, dy;
+ Polyline link;
+
+ Polyline(int dx, int dy, Polyline link) {
+ this.dx = dx;
+ this.dy = dy;
+ this.link = link;
+ }
+}
diff --git a/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java b/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java
new file mode 100644
index 0000000..ab10811
--- /dev/null
+++ b/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java
@@ -0,0 +1,84 @@
+package triangle.syntacticAnalyser;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
+
+import triangle.ErrorReporter;
+import triangle.syntacticAnalyzer.Parser;
+import triangle.syntacticAnalyzer.Scanner;
+import triangle.syntacticAnalyzer.SourceFile;
+
+public class TestScanner {
+
+ @Test
+ public void testHi() {
+ compileExpectSuccess("/hi.tri");
+ }
+
+
+ @Test
+ public void testHiNewComment() {
+ compileExpectFailure("/hi-newcomment.tri");
+ }
+
+
+ @Test
+ public void testHiNewComment2() {
+ compileExpectFailure("/hi-newcomment2.tri");
+ }
+
+
+ @Test
+ public void testBarDemo() {
+ compileExpectFailure("/bardemo.tri");
+ }
+
+
+ @Test
+ public void testRepeatUntil() {
+ compileExpectFailure("/repeatuntil.tri");
+ }
+
+
+
+ private void compileExpectSuccess(String filename) {
+ // build.gradle has a line sourceSets.test.resources.srcDir file("$rootDir/programs")
+ // which adds the programs directory to the list of places Java can easily find files
+ // getResource() below searches for a file, which is in /programs
+ //SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString());
+ SourceFile source = SourceFile.fromResource(filename);
+
+ Scanner scanner = new Scanner(source);
+ ErrorReporter reporter = new ErrorReporter(true);
+ Parser parser = new Parser(scanner, reporter);
+
+ parser.parseProgram();
+
+ // we should get to here with no exceptions
+
+ assertEquals("Problem compiling " + filename, 0, reporter.getNumErrors());
+ }
+
+ private void compileExpectFailure(String filename) {
+ //SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString());
+ SourceFile source = SourceFile.fromResource(filename);
+ Scanner scanner = new Scanner(source);
+ ErrorReporter reporter = new ErrorReporter(true);
+ Parser parser = new Parser(scanner, reporter);
+
+ // we expect an exception here as the program has invalid syntax
+ assertThrows(RuntimeException.class, new ThrowingRunnable() {
+ public void run(){
+ parser.parseProgram();
+ }
+ });
+
+ // currently this program will fail
+ assertNotEquals("Problem compiling " + filename, 0, reporter.getNumErrors());
+ }
+
+}
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..88279c3
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,11 @@
+apply plugin: 'java'
+
+sourceCompatibility = 11
+
+subprojects.each { subproject ->
+ evaluationDependsOn(subproject.path)
+}
+
+jar {
+ from subprojects.sourceSets.main.output
+}
\ No newline at end of file
diff --git a/build/libs/Triangle-Tools.jar b/build/libs/Triangle-Tools.jar
new file mode 100644
index 0000000..3d2dbf7
Binary files /dev/null and b/build/libs/Triangle-Tools.jar differ
diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF
new file mode 100644
index 0000000..59499bc
--- /dev/null
+++ b/build/tmp/jar/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7454180
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e750102
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/obj.tam b/obj.tam
new file mode 100644
index 0000000..26e8273
Binary files /dev/null and b/obj.tam differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..596a93b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,19 @@
+
+ 4.0.0
+ triangle.tools
+ triangle-tools
+ 2.1
+ pom
+
+ 17
+ 17
+ UTF-8
+
+
+ Triangle.AbstractMachine
+ Triangle.Compiler
+ Triangle.AbstractMachine.Disassembler
+ Triangle.AbstractMachine.Interpreter
+
+
\ No newline at end of file
diff --git a/programs/adddeep.tri b/programs/adddeep.tri
new file mode 100644
index 0000000..5f33bc1
--- /dev/null
+++ b/programs/adddeep.tri
@@ -0,0 +1,12 @@
+let
+ var a: Integer
+in
+begin
+ a := 10 + 20 * 2 / 3;
+ putint(a);
+
+ puteol();
+
+ a := 5 + 8;
+ putint(a)
+end
diff --git a/programs/arrays.tam b/programs/arrays.tam
new file mode 100644
index 0000000..a3d0afe
Binary files /dev/null and b/programs/arrays.tam differ
diff --git a/programs/arrays.tri b/programs/arrays.tri
new file mode 100644
index 0000000..1cfbd28
--- /dev/null
+++ b/programs/arrays.tri
@@ -0,0 +1,47 @@
+let
+ type Vector ~ array 3 of Integer;
+ type Matrix ~ array 3 of Vector;
+
+ proc putvector (v: Vector) ~
+ let var i: Integer
+ in
+ begin
+ put ('['); putint (v[0]);
+ i := 1;
+ while i < 3 do
+ begin
+ put (' '); putint (v[i]);
+ i := i+1
+ end;
+ put (']')
+ end;
+
+ proc putmatrix (m: Matrix) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < 3 do
+ begin
+ putvector (m[i]);
+ puteol ();
+ i := i+1
+ end
+ end;
+
+ func diagonal
+ (m: Matrix): Vector ~
+ [m[0][0], m[1][1], m[2][2]];
+
+ var me: Matrix
+
+in
+ begin
+ me := [[1,2,3], [4,5,6], [7,8,9]];
+ putmatrix (me); puteol ();
+ putvector (diagonal (me));
+ puteol (); puteol ();
+ me[1] := [10,11,12];
+ me[1][1] := 22;
+ putmatrix (me); puteol ()
+ end
diff --git a/programs/assignments.tri b/programs/assignments.tri
new file mode 100644
index 0000000..102bb78
--- /dev/null
+++ b/programs/assignments.tri
@@ -0,0 +1,9 @@
+let
+ var n : Integer;
+ var c : Char
+in
+
+ begin
+ c := '&';
+ n := n + 1
+ end
diff --git a/programs/bank.tri b/programs/bank.tri
new file mode 100644
index 0000000..e7f3c0f
--- /dev/null
+++ b/programs/bank.tri
@@ -0,0 +1,86 @@
+let
+ const max ~ 9999;
+ const invalid ~ 0-1;
+ type Money ~ Integer; ! 0 .. max
+ type Trans ~ Char; ! 'd' | 'w' | 'q'
+
+ func sum (m: Money, n: Money): Money ~
+ let const s ~ m + n
+ in
+ if s <= max then s else invalid;
+
+ func diff (m: Money, n: Money): Money ~
+ let const d ~ m - n
+ in
+ if 0 <= d then d else invalid;
+
+ proc gettrans (var code: Trans,
+ var amount: Money) ~
+ begin
+ get(var code);
+ if code = 'q' then
+ ! skip
+ else
+ begin
+ getint(var amount);
+ if (0 > amount) \/ (amount > max) then
+ begin
+ amount := invalid; code := '?'
+ end
+ else if (code \= 'd') /\ (code \= 'w') then
+ code := '?'
+ else
+ ! ok
+ end;
+ geteol()
+ end;
+
+ proc processtrans (code: Trans,
+ amount: Money,
+ var balance: Money) ~
+ let
+ var newbalance: Money
+ in
+ begin
+ if code = 'd' then
+ begin
+ put('D'); put('e'); put('p'); put('o'); put('s');
+ put('i'); put('t'); put(' ');
+ putint(amount); puteol();
+ newbalance := sum(balance, amount)
+ end
+ else if code = 'w' then
+ begin
+ put('W'); put('i'); put('t'); put('h'); put('d');
+ put('r'); put('a'); put('w'); put(' ');
+ putint(amount); puteol();
+ newbalance := diff(balance, amount)
+ end
+ else
+ ; !skip
+ if (code = '?') \/ (newbalance = invalid) then
+ begin
+ put('I'); put('n'); put('v'); put('a'); put('l');
+ put('i'); put('d'); puteol()
+ end
+ else
+ balance := newbalance;
+ put('B'); put('a'); put('l'); put('a'); put('n');
+ put('c'); put('e'); put(' ');
+ putint(balance); puteol();
+ end;
+
+ var balance: Money;
+ var amount: Money;
+ var trans: Trans
+
+in
+ begin
+ balance := 0;
+ gettrans(var trans, var amount);
+ while trans \= 'q' do
+ begin
+ processtrans(trans, amount, var balance);
+ gettrans(var trans, var amount)
+ end
+ end
diff --git a/programs/bardemo.tri b/programs/bardemo.tri
new file mode 100644
index 0000000..f730f74
--- /dev/null
+++ b/programs/bardemo.tri
@@ -0,0 +1,19 @@
+! this won't work until after some work in the practicals
+let
+ var a : Integer;
+ var b : Integer
+
+in
+ begin
+ a := 1;
+ b := 2;
+
+ putint(a);
+ puteol();
+ putint(b);
+ puteol();
+ putint(|a);
+ puteol();
+ putint(|b);
+ puteol()
+ end
diff --git a/programs/control.tri b/programs/control.tri
new file mode 100644
index 0000000..9d76146
--- /dev/null
+++ b/programs/control.tri
@@ -0,0 +1,26 @@
+! Plot a histogram from a stream of nonzero integers.
+
+let
+ const mark ~ '+';
+ var n : Integer
+in
+ begin
+ getint (var n); geteol ();
+ while n \= 0 do
+ let
+ var i : Integer;
+ var gap : Integer
+ in
+ begin
+ gap := if n > 0 then 20 else 20 + n;
+ if n < 0 then n := 0 - n else ;
+ i := 0;
+ while i < gap do
+ begin put (' '); i := i + 1 end;
+ i := 0;
+ while i < n do
+ begin put (mark); i := i + 1 end;
+ puteol ();
+ getint (var n); geteol ()
+ end
+ end
diff --git a/programs/deepnest.tri b/programs/deepnest.tri
new file mode 100644
index 0000000..315b123
--- /dev/null
+++ b/programs/deepnest.tri
@@ -0,0 +1,16 @@
+let proc p1 () ~
+ let var c1: Char;
+ proc p2 () ~
+ let proc p3 () ~
+ let proc p4 () ~
+ let proc p5 () ~
+ let proc p6 () ~
+ let proc p7 () ~
+ put (c1)
+ in p7 ()
+ in p6 ()
+ in p5 ()
+ in p4 ()
+ in p3 ()
+ in begin c1 := '+'; p2 () end
+in p1 ()
diff --git a/programs/directories.tri b/programs/directories.tri
new file mode 100644
index 0000000..49e6794
--- /dev/null
+++ b/programs/directories.tri
@@ -0,0 +1,117 @@
+let
+ type Name ~ array 6 of Char;
+ type Number ~ Integer;
+
+ proc prompt () ~
+ begin
+ put('N'); put('a'); put('m'); put('e');
+ put('?'); put(' ')
+ end;
+
+ proc getname (var newname: Name) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < 6 do
+ begin
+ if eol () then
+ newname[i] := ' '
+ else
+ get (var newname[i]);
+ i := i+1
+ end
+ end;
+
+ proc putname (newname: Name) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < 6 do
+ begin
+ put (newname[i]);
+ i := i+1
+ end
+ end;
+
+ type Entry ~ record
+ number: Number,
+ name: Name
+ end;
+ type Directory ~ record
+ size: Integer,
+ entry: array 100 of Entry
+ end;
+
+ proc initialize (var dir: Directory) ~
+ dir.size := 0;
+
+ proc add (var dir: Directory,
+ newname: Name,
+ newnumber: Number) ~
+ begin
+ dir.entry[dir.size] :=
+ {number ~ newnumber, name ~ newname};
+ dir.size := dir.size + 1
+ end;
+
+ proc lookup (var dir: Directory,
+ oldname: Name,
+ var oldnumber: Number,
+ var found: Boolean) ~
+ let
+ var i: Integer;
+ var searching: Boolean
+ in
+ begin
+ i := 0; searching := true;
+ while (i < dir.size) /\ searching do
+ if dir.entry[i].name = oldname then
+ searching := false
+ else
+ i := i+1;
+ found := \searching;
+ if found then
+ oldnumber := dir.entry[i].number
+ else !skip
+ end;
+
+ var mydir: Directory
+
+in
+
+ begin
+ initialize (var mydir);
+ add (var mydir,
+ ['D','a','v','i','d',' '], 6041);
+ add (var mydir,
+ ['M','u','f','f','y',' '], 4969);
+ add (var mydir,
+ ['K','i','e','r','a','n'], 6042);
+ add (var mydir,
+ ['A','l','e','x','a',' '], 5322);
+
+ let
+ const blank ~ [' ', ' ', ' ', ' ', ' ', ' '];
+ var name: Name;
+ var num: Number;
+ var ok: Boolean
+ in
+ begin
+ prompt ();
+ getname (var name); geteol ();
+ while name \= blank do
+ begin
+ putname (name); put (' ');
+ lookup (var mydir, name, var num, var ok);
+ if ok then
+ putint (num)
+ else
+ put ('?');
+ puteol ();
+ prompt ();
+ getname (var name); geteol ()
+ end
+ end
+ end
diff --git a/programs/errors.tri b/programs/errors.tri
new file mode 100644
index 0000000..ed0e097
--- /dev/null
+++ b/programs/errors.tri
@@ -0,0 +1,30 @@
+! Program with a variety of contextual errors.
+
+let
+ type String ~ array 4 of Char;
+ type Name ~ array 3 of String;
+ type Rec ~ record x: Integer, x: Integer end;
+
+ var me: Name;
+ var silly : maxint;
+ var silly: Rec;
+
+ proc putstr (s: String) ~
+ let var i: Integer
+ in
+ begin
+ s[4] := ' ';
+ i := 0;
+ while i do
+ begin i := i+true;
+ put (s[\i])
+ end
+ end
+
+in
+ begin
+ me[true] := ['T','i','n','y'];
+ me[2][2] := 0;
+ put (me[1]); put (4); put ();
+ putstr (initials (me)); puteol ()
+ end
diff --git a/programs/every.tri b/programs/every.tri
new file mode 100644
index 0000000..011fd1c
--- /dev/null
+++ b/programs/every.tri
@@ -0,0 +1,148 @@
+! Marry a woman and man.
+! Input following data for each person (woman then man):
+! surname, forename (each up to 10 non-blank chars),
+! sex ('M'|'F'), marital status ('m'|'u'),
+! day, month, year of birth.
+
+let
+ type Month ~ Integer;
+ const Jan ~ 1; const Feb ~ 2; const Mar ~ 3;
+ const Apr ~ 4; const May ~ 5; const Jun ~ 6;
+ const Jul ~ 7; const Aug ~ 8; const Sep ~ 9;
+ const Oct ~ 10; const Nov ~ 11; const Dec ~ 12;
+
+ type Date ~ record
+ y : Integer,
+ m : Month,
+ d : Integer
+ end;
+ const today ~ {y ~ 1993, m ~ Apr, d ~ 1};
+
+ proc getdate (var date : Date) ~
+ begin
+ getint (var date.d); getint (var date.m); getint (var date.y)
+ end;
+
+ proc putdate (date : Date) ~
+ begin
+ putint (date.d); put ('/');
+ putint (date.m); put ('/');
+ putint (date.y // 100)
+ end;
+
+ func yearsbefore (yrs : Integer, date : Date) : Date ~
+ {y ~ date.y - yrs, m ~ date.m, d ~ date.d};
+
+ func earlier (date1 : Date, date2 : Date) : Boolean ~
+ if date1.y < date2.y then true
+ else if date1.y > date2.y then false
+ else if date1.m < date2.m then true
+ else if date1.m > date2.m then false
+ else date1.d < date2.d;
+
+ const maxname ~ 10;
+ type Name ~ array 10 of Char;
+
+ proc getname (var name : Name) ~
+ let
+ var ch : Char;
+ var length : Integer
+ in
+ begin
+ get (var ch); while ch = ' ' do get (var ch);
+ length := 0;
+ while length < maxname do
+ begin
+ length := length + 1; name[length] := ch;
+ if ch \= ' ' then get (var ch) else ! skip
+ end
+ end;
+
+ proc putname (name : Name) ~
+ let
+ var pad : Boolean;
+ var length : Integer
+ in
+ begin
+ pad := false; length := 0;
+ while (\ pad) /\ (length < maxname) do
+ begin
+ length := length + 1;
+ if name[length] = ' ' then
+ pad := true
+ else
+ put (name[length])
+ end
+ end;
+
+ type Person ~ record
+ surname : Name,
+ forename : Name,
+ male : Boolean,
+ married : Boolean,
+ dob : Date
+ end;
+
+ proc getperson (var person : Person) ~
+ let
+ var fore : Name;
+ var sur : Name;
+ var s : Char;
+ var m : Char;
+ var birth : Date
+ in
+ begin
+ getname (var sur); getname (var fore);
+ get (var s); while s = ' ' do get (var s);
+ get (var m); while m = ' ' do get (var m);
+ getdate (var birth);
+ person := {surname ~ sur, forename ~ fore,
+ male ~ (s = 'M'), married ~ (m = 'm'),
+ dob ~ birth}
+ end;
+
+ proc putperson (person : Person) ~
+ begin
+ putname (person.surname); put (' ');
+ putname (person.forename); put (' ');
+ put (if person.male then 'M' else 'F'); put (' ');
+ put (if person.married then 'm' else 'u'); put (' ');
+ putdate (person.dob)
+ end;
+
+ func age (person : Person) : Integer ~
+ let
+ const dob ~ person.dob
+ in
+ if (today.m > dob.m) \/
+ ((today.m = dob.m) /\ (today.d >= dob.d))
+ then today.y - dob.y
+ else today.y - dob.y - 1;
+
+ const latestdob ~ yearsbefore (16, today);
+
+ var bride : Person;
+ var groom : Person
+
+in
+ begin
+ getperson (var bride);
+ getperson (var groom);
+ puteol ();
+ if \ bride.male /\ groom.male /\
+ \ (bride.married \/ groom.married) /\
+ \ earlier (latestdob, bride.dob) /\
+ \ earlier (latestdob, groom.dob) then
+ begin
+ put ('O'); put ('K'); puteol ();
+ bride.married := true; groom.married := true;
+ bride.surname := groom.surname
+ end
+ else
+ begin
+ put ('N'); put ('o'); put ('!'); puteol ()
+ end;
+ putperson (bride); put (' '); putint (age (bride)); puteol ();
+ putperson (groom); put (' '); putint (age (groom)); puteol ();
+ putdate (today); puteol ()
+ end
diff --git a/programs/factorials.tri b/programs/factorials.tri
new file mode 100644
index 0000000..c1db33c
--- /dev/null
+++ b/programs/factorials.tri
@@ -0,0 +1,15 @@
+let
+ func factorial (n: Integer): Integer ~
+ if n <= 1
+ then 1
+ else n * factorial (n-1);
+
+ var i: Integer
+
+in
+ begin
+ getint (var i);
+ putint (i); put ('!');
+ put (' '); put ('='); put (' ');
+ putint (factorial (i))
+ end
diff --git a/programs/functions.tri b/programs/functions.tri
new file mode 100644
index 0000000..d343874
--- /dev/null
+++ b/programs/functions.tri
@@ -0,0 +1,28 @@
+! Print powers of integers.
+
+let
+ func even (n : Integer) : Boolean ~
+ (n // 2) = 0;
+
+ func sqr (n : Integer) : Integer ~
+ n * n;
+
+ func power (b : Integer, n : Integer) : Integer ~
+ ! assume n >= 0
+ if n = 0
+ then 1
+ else
+ if even (n)
+ then sqr (power (b, n/2))
+ else sqr (power (b, n/2)) * b;
+
+ var x : Integer;
+ var m : Integer
+in
+ begin
+ getint (var x); getint (var m);
+ putint (x); put ('^'); putint (m);
+ put (' '); put ('='); put (' ');
+ putint (power (x, m));
+ puteol ()
+ end
diff --git a/programs/hi-newcomment.tri b/programs/hi-newcomment.tri
new file mode 100644
index 0000000..0929f38
--- /dev/null
+++ b/programs/hi-newcomment.tri
@@ -0,0 +1,7 @@
+! this won't work until after some work in the practicals
+
+# new comment
+
+begin
+ put('H'); put('i'); put('!')
+end
diff --git a/programs/hi-newcomment2.tri b/programs/hi-newcomment2.tri
new file mode 100644
index 0000000..4e764fc
--- /dev/null
+++ b/programs/hi-newcomment2.tri
@@ -0,0 +1,11 @@
+! this won't work until after some work in the practicals
+
+# new comment
+
+$
+another new comment
+$
+
+begin
+ put('H'); put('i'); put('!')
+end
diff --git a/programs/hi.tam b/programs/hi.tam
new file mode 100644
index 0000000..26e8273
Binary files /dev/null and b/programs/hi.tam differ
diff --git a/programs/hi.tri b/programs/hi.tri
new file mode 100644
index 0000000..aac4ec1
--- /dev/null
+++ b/programs/hi.tri
@@ -0,0 +1,3 @@
+begin
+ put('H'); put('i'); put('!')
+end
diff --git a/programs/hullo.tri b/programs/hullo.tri
new file mode 100644
index 0000000..a7a40a0
--- /dev/null
+++ b/programs/hullo.tri
@@ -0,0 +1,53 @@
+let
+ const maxlength ~ 15;
+ type String ~ array 16 of Char;
+ const null ~ chr(0);
+!Strings will be padded with nulls.
+
+ proc getstring (var s: String) ~
+ let var l: Integer
+ in
+ begin
+ l := 0;
+ while l < maxlength do
+ begin
+ if eol () then
+ s[l] := null
+ else
+ get (var s[l]);
+ l := l+1;
+ end;
+ s[maxlength] := null
+ end;
+
+ proc putstring (s: String) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while s[i] \= null do
+ begin
+ put (s[i]);
+ i := i+1
+ end
+ end;
+
+ var you: String
+
+in
+ begin
+ putstring (
+ ['W','h','o',' ',
+ 'a','r','e',' ',
+ 'y','o','u','?',
+ null,null,null,null]);
+ puteol ();
+ getstring (var you); geteol ();
+ putstring (
+ ['H','u','l','l',
+ 'o',',',' ',null,
+ null,null,null,null,
+ null,null,null,null]);
+ putstring (you); put ('!');
+ puteol ()
+end
diff --git a/programs/ifdemo.tri b/programs/ifdemo.tri
new file mode 100644
index 0000000..ddc4df3
--- /dev/null
+++ b/programs/ifdemo.tri
@@ -0,0 +1,9 @@
+let
+ var a : Integer;
+ var n : Integer
+in
+ begin
+ if a < 0
+ then n := 0
+ else n := 1
+ end
diff --git a/programs/increment.tri b/programs/increment.tri
new file mode 100644
index 0000000..11358a5
--- /dev/null
+++ b/programs/increment.tri
@@ -0,0 +1,14 @@
+! this won't compile without implementing the bonus material in Practical 3
+
+let
+ var a: Integer
+in
+begin
+ getint(var a);
+ a++;
+ putint(a);
+ puteol();
+ a++;
+ putint(a);
+ puteol();
+end
diff --git a/programs/names.tri b/programs/names.tri
new file mode 100644
index 0000000..741167a
--- /dev/null
+++ b/programs/names.tri
@@ -0,0 +1,52 @@
+let
+ type Name ~ array 6 of Char;
+ type Number ~ Integer;
+
+ proc getname (var newname: Name) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < 6 do
+ begin
+ if eol () then
+ newname[i] := ' '
+ else
+ get (var newname[i]);
+ i := i+1
+ end
+ end;
+
+ proc putname (newname: Name) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < 6 do
+ begin
+ put (newname[i]);
+ i := i+1
+ end
+ end;
+
+ func samename (name1: Name, name2: Name) : Boolean ~
+ let
+ func same (n: Integer) : Boolean ~
+ (name1[n] = name2[n]) /\
+ (if n = 0 then true else same (n-1))
+ in
+ same (5);
+
+ var nam: Name
+
+in
+
+ begin
+ getname (var nam); geteol ();
+ putname (nam); put (' ');
+ if samename (nam, ['D','a','v','i','d',' ']) then
+ put ('Y')
+ else
+ put ('N');
+ puteol ()
+ end
diff --git a/programs/nesting.tri b/programs/nesting.tri
new file mode 100644
index 0000000..90838ca
--- /dev/null
+++ b/programs/nesting.tri
@@ -0,0 +1,31 @@
+let
+ var g: Integer;
+
+ proc P() ~
+ let
+ var p: Integer;
+
+ proc Q() ~
+ let
+ var q: Integer;
+ proc R() ~
+ let
+ var r: Integer
+ in
+ r := (g+p+q) * 1000 ! should cause overflow
+ in
+ begin q := g+p; R() end;
+
+ proc S() ~
+ let
+ var s: Integer
+ in
+ begin s := g+p+1; Q() end
+
+ in
+ begin p := g+1; S() end
+
+in
+ begin g := 1000; P() end
+
+
diff --git a/programs/procedural.tri b/programs/procedural.tri
new file mode 100644
index 0000000..65263d0
--- /dev/null
+++ b/programs/procedural.tri
@@ -0,0 +1,56 @@
+! test program proc.Æ
+let
+ const size ~ 6;
+ type String ~ array 6 of Char;
+
+ proc putstr (s: String) ~
+ let var i: Integer
+ in
+ begin
+ i := 0;
+ while i < size do
+ begin put (s[i]); i := i+1 end
+ end;
+
+ proc apply (proc p (var c : Char), var s : String) ~
+ let
+ var i : Integer
+ in
+ begin
+ i := 0;
+ while i < size do
+ begin
+ p (var s[i]);
+ i := i+1
+ end
+ end; !apply
+
+ proc shift (var l : Char) ~
+ let const ordl ~ ord (l)
+ in
+ if (ord('a') <= ordl)
+ /\ (ordl <= ord('z')) then
+ l := chr (ordl - ord('a') + ord('A'))
+ else
+ ; !skip
+
+ proc replaceall (old: Char, new: Char,
+ var s: String) ~
+ let
+ proc zap (var c: Char) ~
+ if c = old then c := new else !skip
+ in
+ apply (proc zap, var s);
+
+ var name : String
+
+in
+ begin
+ apply (proc get, var name);
+ geteol ();
+ putstr (name); puteol ();
+ apply (proc shift, var name);
+ putstr (name); puteol ();
+ replaceall ('I', 'i', var name);
+ putstr (name); puteol ()
+ end
diff --git a/programs/procedures.tri b/programs/procedures.tri
new file mode 100644
index 0000000..a72f68c
--- /dev/null
+++ b/programs/procedures.tri
@@ -0,0 +1,31 @@
+! Plot a histogram from a stream of nonzero integers.
+
+let
+ const mid ~ 40;
+ var n : Integer;
+
+ proc putmany (c : Char, n : Integer) ~
+ let
+ var i : Integer
+ in
+ begin
+ i := 0;
+ while i < n do
+ begin put (c); i := i + 1 end
+ end;
+
+ proc makenonnegative (var n : Integer) ~
+ if n < 0 then n := 0 - n else
+
+in
+ begin
+ getint (var n); geteol ();
+ while n \= 0 do
+ begin
+ putmany (' ', if n > 0 then mid else mid + n);
+ makenonnegative (var n);
+ putmany ('+', n);
+ puteol ();
+ getint (var n); geteol ()
+ end
+ end
diff --git a/programs/records.tri b/programs/records.tri
new file mode 100644
index 0000000..5d8f63e
--- /dev/null
+++ b/programs/records.tri
@@ -0,0 +1,24 @@
+! test program record.Æ
+let
+ type Month ~ array 3 of Char;
+ type Date ~ record d: Integer, m: Month end;
+ const xmas ~ {d ~ 25,
+ m ~ ['D','e','c']};
+ var eve: Date;
+
+ proc putmonth (mth: Month) ~
+ begin
+ put (mth[0]); put (mth[1]); put (mth[2])
+ end;
+
+ proc putdate (date: Date) ~
+ begin
+ putint (date.d); put ('/'); putmonth (date.m)
+ end
+
+in
+ begin
+ putdate (xmas); puteol ();
+ eve := {d ~ xmas.d-1, m ~ xmas.m};
+ putdate (eve); puteol ()
+ end
\ No newline at end of file
diff --git a/programs/repeatuntil.tri b/programs/repeatuntil.tri
new file mode 100644
index 0000000..c2518de
--- /dev/null
+++ b/programs/repeatuntil.tri
@@ -0,0 +1,14 @@
+! this won't work until after some lab work
+
+let
+ var a : Integer
+in
+begin
+ a := 0;
+ repeat
+ begin
+ put('a');
+ a := a + 1;
+ end
+ until a >= 5
+end
diff --git a/programs/repl.tri b/programs/repl.tri
new file mode 100644
index 0000000..f6cf367
--- /dev/null
+++ b/programs/repl.tri
@@ -0,0 +1,13 @@
+let
+ type Str ~ array 10 of Char;
+
+ func replicate (c: Char): Str ~
+ [c,c,c,c,c,c,c,c,c,c];
+
+ var s: Str
+in
+
+ begin
+ s := replicate('*');
+ put (s[0]); put(s[9]); puteol()
+ end
diff --git a/programs/run b/programs/run
new file mode 100755
index 0000000..84ed354
--- /dev/null
+++ b/programs/run
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Term colours for output
+RED='\033[0;31m' # Red
+GRN='\033[0;32m' # Green
+NC='\033[0m' # No Color
+
+TRI=""
+
+# Check if the input in arg 1 ($1) is empty
+if [ -z "$1" ]
+ then # if empty...
+ printf "${RED}Usage: $0 *.tri file (optional: $0 *.tri tree)${NC}"
+ exit 1 # Exit with code 1, failure
+ else
+ TRI=$1
+fi
+
+#Remove the extension of the file
+FILENAME=$(echo $TRI | cut -f 1 -d '.')
+
+#TODO: implement tree command
+printf "${GRN}[INFO] Compiling file: $FILENAME.tri to $FILENAME.tam ...${NC}\n"
+
+# Compile to tam
+if java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri -o=$FILENAME.tam &> /dev/null #quiet
+ then if [ -z "$2" ]
+ then #if empty
+ printf "${GRN}[INFO] Running file: $FILENAME.tam ...${NC}\n"
+ java -cp ../build/libs/Triangle-Tools.jar triangle.abstractMachine.Interpreter $FILENAME.tam
+ exit 0
+ else
+ printf "${GRN}[INFO] Running file: $FILENAME.tam ... and displaying AST${NC}\n"
+ java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri tree -o=$FILENAME.tam &> /dev/null #quiet
+ exit 0
+ fi
+
+ else
+ printf "${RED}[ERROR] Could not complie $FILENAME.tri ...${NC}"
+ err=$(java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri -o=$FILENAME.tam)
+ printf "${RED}\n$err\n${NC}"
+ exit 1
+fi
diff --git a/programs/simpleadding.tri b/programs/simpleadding.tri
new file mode 100644
index 0000000..139847a
--- /dev/null
+++ b/programs/simpleadding.tri
@@ -0,0 +1,10 @@
+let
+ var a : Integer;
+ var b : Integer;
+ var c : Integer
+
+in
+ begin
+ a := 1; b := 2; c := a / b;
+ end
+
diff --git a/programs/triangle.tam b/programs/triangle.tam
new file mode 100644
index 0000000..87d30f3
Binary files /dev/null and b/programs/triangle.tam differ
diff --git a/programs/triangle.tri b/programs/triangle.tri
new file mode 100644
index 0000000..555ea81
--- /dev/null
+++ b/programs/triangle.tri
@@ -0,0 +1,32 @@
+let
+
+ proc putmany (n: Integer, c: Char) ~
+ let
+ var i: Integer
+ in
+ begin
+ i := 0;
+ while i < n do
+ begin i := i+1; put (c) end
+ end;
+
+ var n: Integer; var r: Integer;
+ const mark ~ '@'
+
+in
+ begin
+ getint (var n); geteol ();
+ r := 0;
+ while r < (n-1) do
+ begin
+ r := r + 1;
+ putmany (n-r, ' '); put (mark);
+ if r >= 2 then
+ begin
+ putmany (2*r - 3, ' '); put (mark)
+ end
+ else; !skip
+ puteol ()
+ end;
+ putmany (2*n - 1, mark)
+ end
diff --git a/programs/while-longloop.tri b/programs/while-longloop.tri
new file mode 100644
index 0000000..75b1088
--- /dev/null
+++ b/programs/while-longloop.tri
@@ -0,0 +1,22 @@
+let
+ var a : Integer;
+ var b : Integer;
+ var c : Integer
+in
+begin
+ put('1');
+ puteol();
+ a := 0;
+ while a < 5000 do
+ begin
+ b := 0;
+ while b < 3000 do
+ begin
+ c := c + a;
+ c := c / (1 + b);
+ b := b + 1;
+ end;
+ a := a + 1;
+ end;
+ putint(c);
+end
diff --git a/programs/while.tri b/programs/while.tri
new file mode 100644
index 0000000..9bbb664
--- /dev/null
+++ b/programs/while.tri
@@ -0,0 +1,11 @@
+let
+ var a : Integer
+in
+begin
+ a := 0;
+ while a < 5 do
+ begin
+ put('a');
+ a := a + 1;
+ end
+end
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..5e273cd
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,7 @@
+rootProject.name = 'Triangle-Tools'
+
+include 'Triangle.Compiler'
+include 'Triangle.AbstractMachine'
+include 'Triangle.AbstractMachine.Disassembler'
+include 'Triangle.AbstractMachine.Interpreter'
+