diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7ff3503
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,62 @@
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+.vscode
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+/.gradle/
diff --git a/.project b/.project
new file mode 100644
index 0000000..4beb8b6
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ a5-triangle-tools
+ Project a5-triangle-tools created by Buildship.
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectnature
+
+
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..0b564b1
--- /dev/null
+++ b/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java
@@ -0,0 +1,355 @@
+/*
+ * @(#)Disassembler.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..973baf5
--- /dev/null
+++ b/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java
@@ -0,0 +1,649 @@
+/*
+ * @(#)Interpreter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..16f3fe9
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java
@@ -0,0 +1,71 @@
+/*
+ * @(#)Instruction.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1bcfd6b
--- /dev/null
+++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java
@@ -0,0 +1,58 @@
+/*
+ * @(#)Machine.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1134923
--- /dev/null
+++ b/Triangle.Compiler/build.gradle
@@ -0,0 +1,24 @@
+apply plugin: 'java'
+apply plugin: 'application'
+
+sourceCompatibility = 11
+
+repositories {
+ mavenCentral()
+}
+
+
+dependencies {
+ implementation project(':Triangle.AbstractMachine')
+ // Task 2
+ implementation group: 'com.github.spullara.cli-parser', name: 'cli-parser', version: '1.1.5'
+ //
+ 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")
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..8416466
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/Compiler.java
@@ -0,0 +1,183 @@
+/*
+ * @(#)Compiler.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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;
+
+// Task 2
+import com.sampullara.cli.Args;
+import com.sampullara.cli.Argument;
+
+/**
+ * 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 objectNIame = "obj.tam";
+ //static boolean showTree = false;
+ //static boolean folding = false; //Better implementation below
+
+ 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;
+
+ //Task 2
+
+ @Argument(alias = "file", description="Name of file you want to compile", required = true)
+ static String sourceName = "";
+
+ @Argument(alias = "obj", description="Object file name", required = true)
+ static String objectName = "obj.tam"; //default
+
+ @Argument(alias = "tree", description="Enable AST")
+ static boolean showTree = false;
+
+ @Argument(alias = "fold", description="Enable folding")
+ static boolean folding = false;
+
+ @Argument(alias = "tfold", description="Enable AST after folding")
+ static boolean showTreeAfterFolding = false;
+
+ //Task 5b
+ @Argument(alias = "stats", description="Enable stats (Char and Int Expr count)")
+ static boolean showStats = false;
+
+ /**
+ * 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).
+ * @param showAfterFolding show the AST after folding is complete
+ * @param showStats show stats, these only (so far) inlcude char and int expressions
+ * @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, boolean showAfterFolding, boolean showStats) {
+
+ 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();
+
+ //Task 5b
+ stats = new SummaryStats();
+
+ theAST = parser.parseProgram(); // 1st pass
+ if (reporter.getNumErrors() == 0) {
+ System.out.println("Contextual Analysis ...");
+ checker.check(theAST); // 2nd pass
+
+ if (showingAST && !showAfterFolding) {
+ drawer.draw(theAST);
+ }
+ if (folding) {
+ theAST.visit(new ConstantFolder());
+ if (showingAST && showAfterFolding) {
+ drawer.draw(theAST); //if folding then also show tree
+ }
+ }
+
+
+ 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.");
+ //Task 5b
+ System.out.println("[STATS] CharExpr: " + stats.getCharExprCount() + "!");
+ System.out.println("[STATS] IntExpr: " + stats.getIntExprCount() + "!");
+ } 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) {
+
+ //Task 2
+ Args.parseOrExit(Compiler.class, args);
+ var compiledOK = compileProgram(Compiler.sourceName, Compiler.objectName, Compiler.showTree, false, Compiler.showTreeAfterFolding);
+
+ if (!showTree) {
+ System.exit(compiledOK ? 0 : 1);
+ }
+ }
+
+ /* No longer needed */
+ 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..35a813d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java
@@ -0,0 +1,65 @@
+/*
+ * @(#)ErrorReporter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..6b86b48
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java
@@ -0,0 +1,50 @@
+/*
+ * @(#)StdEnvironment.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8bccf00
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java
@@ -0,0 +1,38 @@
+/*
+ * @(#)AST.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..92dfa7e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)Program.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..404766a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)ActualParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d4f3aaa
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)ActualParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..ca93044
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)ConstActualParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..46c4d4e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)EmptyActualParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..40c7f1f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)FuncActualParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b26b9d3
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)MultipleActualParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..a525a4e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)ProcActualParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..5ec7087
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)SingleActualParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..2ffc54e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)VarActualParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..359cd1b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)ArrayAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..c554b77
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)MultipleArrayAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..5b12468
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java
@@ -0,0 +1,42 @@
+/*
+ * @(#)MultipleRecordAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..153a367
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)RecordAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8ccf165
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)SingleArrayAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..f4f18d1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)SingleRecordAggregate.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..030f513
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)AssignCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1fa3d58
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)CallCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..e4d06ce
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java
@@ -0,0 +1,36 @@
+/*
+ * @(#)Command.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8e4ac82
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)EmptyCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..bde0333
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)IfCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d00d873
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)LetCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..2922f65
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)SequentialCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..a0e69ee
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)WhileCommand.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..ba3497c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)BinaryOperatorDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b60c3ba
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java
@@ -0,0 +1,46 @@
+/*
+ * @(#)ConstDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b20340b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)Declaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..fb0b6b1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java
@@ -0,0 +1,57 @@
+/*
+ * @(#)FuncDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..fb1ba97
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)ProcDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1f5b1e7
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)SequentialDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..185647c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)UnaryOperatorDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..bb29245
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * @(#)VarDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1306df4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)ArrayExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..eee1e0e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)BinaryExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..0aeb2e2
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)CallExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..e8b549b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)CharacterExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..ed67191
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)EmptyExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..a3f6f27
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)Expression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..059fb78
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)IfExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b0c8406
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)IntegerExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..2e2e144
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)LetExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..e9467e4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)RecordExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..836e8f7
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)UnaryExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8a04c73
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)VnameExpression.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..9d66e10
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java
@@ -0,0 +1,55 @@
+/*
+ * @(#)ConstFormalParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d844880
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java
@@ -0,0 +1,38 @@
+/*
+ * @(#)EmptyFormalParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..9248f7f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)FormalParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..dc08d07
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)FormalParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..eeb62e7
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java
@@ -0,0 +1,63 @@
+/*
+ * @(#)FuncFormalParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d6c5a9a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java
@@ -0,0 +1,49 @@
+/*
+ * @(#)MultipleFormalParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..80a49e1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java
@@ -0,0 +1,55 @@
+/*
+ * @(#)ProcFormalParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..cd624c1
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java
@@ -0,0 +1,46 @@
+/*
+ * @(#)SingleFormalParameterSequence.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..5bbdbbd
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java
@@ -0,0 +1,55 @@
+/*
+ * @(#)ValFormalParameter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..6fe99ca
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)CharacterLiteral.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..f8fec82
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)Identifier.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..e15bab2
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)IntegerLiteral.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..9dccdb8
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)Operator.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b970211
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java
@@ -0,0 +1,32 @@
+/*
+ * @(#)Terminal.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..2975ed0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)AnyTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..39c474a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java
@@ -0,0 +1,56 @@
+/*
+ * @(#)ArrayTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..ee24e5a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)BoolTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..c01d7f2
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)CharTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..3e0e7e4
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)ErrorTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8a9eecf
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java
@@ -0,0 +1,28 @@
+/*
+ * @(#)FieldTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..5b593c3
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)IntTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..3a77a3a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java
@@ -0,0 +1,57 @@
+/*
+ * @(#)MultipleFieldTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..3907a5a
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java
@@ -0,0 +1,52 @@
+/*
+ * @(#)RecordTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..198814b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)SimpleTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..16cd5cb
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java
@@ -0,0 +1,54 @@
+/*
+ * @(#)SingleFieldTypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..0a90928
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)TypeDeclaration.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..977fc7c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java
@@ -0,0 +1,41 @@
+/*
+ * @(#)TypeDenoter.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..7a0538c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)DotVname.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..05354af
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)SimpleVname.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..010d194
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)SubscriptVname.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..0b701fc
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)Vname.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..c883070
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java
@@ -0,0 +1,796 @@
+/*
+ * @(#)Encoder.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..ba5e217
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java
@@ -0,0 +1,77 @@
+/*
+ * @(#)Frame.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..0b2c1da
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java
@@ -0,0 +1,50 @@
+/*
+ * @(#)EqualityRoutine.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b0daf9e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)Field.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..587d9df
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java
@@ -0,0 +1,66 @@
+/*
+ * @(#)KnownAddress.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..5a4c22b
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)KnownRoutine.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..f8147e8
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)KnownValue.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..791d028
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)ObjectAddress.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..29424ac
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java
@@ -0,0 +1,51 @@
+/*
+ * @(#)PrimitiveRoutine.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..273371c
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java
@@ -0,0 +1,34 @@
+/*
+ * @(#)RuntimeEntity.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..35c71e0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java
@@ -0,0 +1,27 @@
+/*
+ * @(#)TypeRepresentation.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..c3d6054
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java
@@ -0,0 +1,78 @@
+/*
+ * @(#)UnknownAddress.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..c7a080d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)UnknownRoutine.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8077e69
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java
@@ -0,0 +1,55 @@
+/*
+ * @(#)UnknownValue.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d06813e
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java
@@ -0,0 +1,984 @@
+/*
+ * @(#)Checker.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..7b79de0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java
@@ -0,0 +1,37 @@
+/*
+ * @(#)IdEntry.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..8807a01
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java
@@ -0,0 +1,91 @@
+/*
+ * @(#)IdentificationTable.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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/optimiser/SummaryStats.java b/Triangle.Compiler/src/main/java/triangle/optimiser/SummaryStats.java
new file mode 100644
index 0000000..973b5b5
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/optimiser/SummaryStats.java
@@ -0,0 +1,614 @@
+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 SummaryStats implements ActualParameterVisitor,
+ ActualParameterSequenceVisitor, ArrayAggregateVisitor,
+ CommandVisitor, DeclarationVisitor,
+ ExpressionVisitor, FormalParameterSequenceVisitor,
+ IdentifierVisitor, LiteralVisitor,
+ OperatorVisitor, ProgramVisitor,
+ RecordAggregateVisitor, TypeDenoterVisitor,
+ VnameVisitor {
+ {
+
+ }
+
+ //Task 5
+ public int countCharExpr;
+ public int countIntExpr;
+
+ public int getCharExprCount() {
+ return countCharExpr;
+ }
+
+ public int getIntExprCount() {
+ return countIntExpr;
+ }
+
+
+ @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) {
+ countCharExpr++; //Increment the count for stats
+ 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) {
+ countIntExpr++; //Increment the count for stats
+ 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..e00e268
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java
@@ -0,0 +1,948 @@
+/*
+ * @(#)Parser.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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);
+ //Task 3 a**
+ if (currentToken.kind == Token.OPERATOR && currentToken.spelling.equals("**")) {
+ acceptIt();
+
+ IntegerLiteral intLit = new IntegerLiteral("2", commandPos);
+ IntegerExpression intExp = new IntegerExpression(intLit, commandPos);
+
+ VnameExpression vNameExp = new VnameExpression(vAST, commandPos);
+ Operator oper = new Operator("*", commandPos);
+
+ Expression eAST = new BinaryExpression(vNameExp, oper, intExp, commandPos );
+
+ finish(commandPos);
+
+ commandAST = new AssignCommand(vAST, eAST, commandPos);
+ } else {
+ 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;
+
+ //Task 4
+ case Token.LCURLY:
+ acceptIt();
+ commandAST = parseCommand();
+ accept(Token.RCURLY);
+ break;
+
+ case Token.SEMICOLON:
+ case Token.END:
+ case Token.ELSE:
+ case Token.IN:
+ case Token.EOT:
+ case Token.RCURLY:
+
+ 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..a6f0f42
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java
@@ -0,0 +1,276 @@
+/*
+ * @(#)Scanner.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..2741f44
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java
@@ -0,0 +1,72 @@
+/*
+ * @(#)SourceFile.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..f3a7e0f
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java
@@ -0,0 +1,39 @@
+/*
+ * @(#)SourcePosition.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..639a2ba
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)SyntaxError.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..614c344
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java
@@ -0,0 +1,88 @@
+/*
+ * @(#)Token.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..1d7ab2d
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java
@@ -0,0 +1,72 @@
+/*
+ * @(#)Drawer.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..81b6894
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java
@@ -0,0 +1,78 @@
+/*
+ * @(#)DrawerFrame.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..d11eac9
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java
@@ -0,0 +1,43 @@
+/*
+ * @(#)DrawerPanel.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..85a7947
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java
@@ -0,0 +1,88 @@
+/*
+ * @(#)DrawingTree.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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..b5ffec0
--- /dev/null
+++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java
@@ -0,0 +1,684 @@
+/*
+ * @(#)LayoutVisitor.java
+ *
+ * Revisions and updates (c) 2022-2023 Sandy Brownlee. alexander.brownlee@stir.ac.uk
+ *
+ * Original release:
+ *
+ * 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