From 3655a949f3a68eb4c0a51aea8b1b717622427650 Mon Sep 17 00:00:00 2001 From: simonkellet Date: Mon, 18 Sep 2023 15:30:32 +0100 Subject: [PATCH] initial push --- LICENSE | 21 + .../.gitignore | 3 + .../.project | 23 + .../build.gradle | 12 + Triangle.AbstractMachine.Disassembler/pom.xml | 18 + .../abstractMachine/Disassembler.java | 351 +++++++ .../.gitignore | 3 + Triangle.AbstractMachine.Interpreter/.project | 23 + .../build.gradle | 12 + Triangle.AbstractMachine.Interpreter/pom.xml | 18 + .../triangle/abstractMachine/Interpreter.java | 645 ++++++++++++ Triangle.AbstractMachine/.gitignore | 3 + Triangle.AbstractMachine/.project | 23 + Triangle.AbstractMachine/build.gradle | 4 + Triangle.AbstractMachine/pom.xml | 12 + .../triangle/abstractMachine/Instruction.java | 67 ++ .../triangle/abstractMachine/Machine.java | 54 + .../java/triangle/abstractMachine/OpCode.java | 5 + .../triangle/abstractMachine/Primitive.java | 6 + .../triangle/abstractMachine/Register.java | 5 + Triangle.Compiler/.gitignore | 4 + Triangle.Compiler/.project | 23 + Triangle.Compiler/build.gradle | 21 + Triangle.Compiler/pom.xml | 18 + .../src/main/java/triangle/Compiler.java | 152 +++ .../src/main/java/triangle/ErrorReporter.java | 61 ++ .../main/java/triangle/StdEnvironment.java | 46 + .../AbstractSyntaxTree.java | 34 + .../triangle/abstractSyntaxTrees/Program.java | 37 + .../actuals/ActualParameter.java | 32 + .../actuals/ActualParameterSequence.java | 32 + .../actuals/ConstActualParameter.java | 33 + .../actuals/EmptyActualParameterSequence.java | 29 + .../actuals/FuncActualParameter.java | 33 + .../MultipleActualParameterSequence.java | 35 + .../actuals/ProcActualParameter.java | 33 + .../SingleActualParameterSequence.java | 32 + .../actuals/VarActualParameter.java | 33 + .../aggregates/ArrayAggregate.java | 35 + .../aggregates/MultipleArrayAggregate.java | 35 + .../aggregates/MultipleRecordAggregate.java | 38 + .../aggregates/RecordAggregate.java | 36 + .../aggregates/SingleArrayAggregate.java | 33 + .../aggregates/SingleRecordAggregate.java | 36 + .../commands/AssignCommand.java | 36 + .../commands/CallCommand.java | 36 + .../abstractSyntaxTrees/commands/Command.java | 32 + .../commands/EmptyCommand.java | 29 + .../commands/IfCommand.java | 36 + .../commands/LetCommand.java | 35 + .../commands/SequentialCommand.java | 33 + .../commands/WhileCommand.java | 35 + .../BinaryOperatorDeclaration.java | 39 + .../declarations/ConstDeclaration.java | 42 + .../declarations/ConstantDeclaration.java | 9 + .../declarations/Declaration.java | 35 + .../declarations/FuncDeclaration.java | 53 + .../declarations/FunctionDeclaration.java | 12 + .../declarations/ProcDeclaration.java | 44 + .../declarations/ProcedureDeclaration.java | 9 + .../declarations/SequentialDeclaration.java | 33 + .../UnaryOperatorDeclaration.java | 37 + .../declarations/VarDeclaration.java | 41 + .../declarations/VariableDeclaration.java | 9 + .../expressions/ArrayExpression.java | 33 + .../expressions/BinaryExpression.java | 37 + .../expressions/CallExpression.java | 36 + .../expressions/CharacterExpression.java | 43 + .../expressions/EmptyExpression.java | 29 + .../expressions/Expression.java | 44 + .../expressions/IfExpression.java | 36 + .../expressions/IntegerExpression.java | 43 + .../expressions/LetExpression.java | 35 + .../expressions/RecordExpression.java | 33 + .../expressions/UnaryExpression.java | 35 + .../expressions/VnameExpression.java | 33 + .../formals/ConstFormalParameter.java | 51 + .../formals/EmptyFormalParameterSequence.java | 34 + .../formals/FormalParameter.java | 35 + .../formals/FormalParameterSequence.java | 35 + .../formals/FuncFormalParameter.java | 59 ++ .../MultipleFormalParameterSequence.java | 45 + .../formals/ProcFormalParameter.java | 51 + .../SingleFormalParameterSequence.java | 42 + .../formals/VarFormalParameter.java | 51 + .../terminals/CharacterLiteral.java | 37 + .../terminals/Identifier.java | 40 + .../terminals/IntegerLiteral.java | 37 + .../terminals/Operator.java | 37 + .../terminals/Terminal.java | 28 + .../types/AnyTypeDenoter.java | 39 + .../types/ArrayTypeDenoter.java | 52 + .../types/BoolTypeDenoter.java | 44 + .../types/CharTypeDenoter.java | 44 + .../types/ErrorTypeDenoter.java | 39 + .../types/FieldTypeDenoter.java | 24 + .../types/IntTypeDenoter.java | 44 + .../types/MultipleFieldTypeDenoter.java | 53 + .../types/RecordTypeDenoter.java | 48 + .../types/SimpleTypeDenoter.java | 43 + .../types/SingleFieldTypeDenoter.java | 50 + .../types/TypeDeclaration.java | 36 + .../types/TypeDenoter.java | 37 + .../ActualParameterSequenceVisitor.java | 15 + .../visitors/ActualParameterVisitor.java | 18 + .../visitors/ArrayAggregateVisitor.java | 12 + .../visitors/CommandVisitor.java | 27 + .../visitors/DeclarationVisitor.java | 30 + .../visitors/ExpressionVisitor.java | 39 + .../visitors/FieldTypeDenoterVisitor.java | 12 + .../FormalParameterSequenceVisitor.java | 15 + .../visitors/FormalParameterVisitor.java | 18 + .../visitors/IdentifierVisitor.java | 9 + .../visitors/LiteralVisitor.java | 12 + .../visitors/OperatorVisitor.java | 9 + .../visitors/ProgramVisitor.java | 9 + .../visitors/RecordAggregateVisitor.java | 12 + .../visitors/TypeDenoterVisitor.java | 30 + .../visitors/VnameVisitor.java | 15 + .../abstractSyntaxTrees/vnames/DotVname.java | 35 + .../vnames/SimpleVname.java | 33 + .../vnames/SubscriptVname.java | 35 + .../abstractSyntaxTrees/vnames/Vname.java | 39 + .../java/triangle/codeGenerator/Emitter.java | 120 +++ .../java/triangle/codeGenerator/Encoder.java | 792 ++++++++++++++ .../java/triangle/codeGenerator/Frame.java | 73 ++ .../entities/AddressableEntity.java | 29 + .../entities/EqualityRoutine.java | 46 + .../entities/FetchableEntity.java | 11 + .../codeGenerator/entities/Field.java | 29 + .../codeGenerator/entities/KnownAddress.java | 62 ++ .../codeGenerator/entities/KnownRoutine.java | 44 + .../codeGenerator/entities/KnownValue.java | 39 + .../codeGenerator/entities/ObjectAddress.java | 35 + .../entities/PrimitiveRoutine.java | 47 + .../codeGenerator/entities/RoutineEntity.java | 11 + .../codeGenerator/entities/RuntimeEntity.java | 30 + .../entities/TypeRepresentation.java | 23 + .../entities/UnknownAddress.java | 74 ++ .../entities/UnknownRoutine.java | 44 + .../codeGenerator/entities/UnknownValue.java | 51 + .../triangle/contextualAnalyzer/Checker.java | 980 ++++++++++++++++++ .../triangle/contextualAnalyzer/IdEntry.java | 33 + .../IdentificationTable.java | 87 ++ .../triangle/optimiser/ConstantFolder.java | 599 +++++++++++ .../triangle/syntacticAnalyzer/Parser.java | 920 ++++++++++++++++ .../triangle/syntacticAnalyzer/Scanner.java | 272 +++++ .../syntacticAnalyzer/SourceFile.java | 68 ++ .../syntacticAnalyzer/SourcePosition.java | 35 + .../syntacticAnalyzer/SyntaxError.java | 29 + .../triangle/syntacticAnalyzer/Token.java | 84 ++ .../main/java/triangle/treeDrawer/Drawer.java | 68 ++ .../java/triangle/treeDrawer/DrawerFrame.java | 74 ++ .../java/triangle/treeDrawer/DrawerPanel.java | 39 + .../java/triangle/treeDrawer/DrawingTree.java | 84 ++ .../triangle/treeDrawer/LayoutVisitor.java | 680 ++++++++++++ .../java/triangle/treeDrawer/Polygon.java | 20 + .../java/triangle/treeDrawer/Polyline.java | 29 + .../syntacticAnalyser/TestScanner.java | 84 ++ build.gradle | 11 + build/libs/Triangle-Tools.jar | Bin 0 -> 172601 bytes build/tmp/jar/MANIFEST.MF | 2 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 234 +++++ gradlew.bat | 89 ++ obj.tam | Bin 0 -> 112 bytes pom.xml | 19 + programs/adddeep.tri | 12 + programs/arrays.tam | Bin 0 -> 1376 bytes programs/arrays.tri | 47 + programs/assignments.tri | 9 + programs/bank.tri | 86 ++ programs/bardemo.tri | 19 + programs/control.tri | 26 + programs/deepnest.tri | 16 + programs/directories.tri | 117 +++ programs/errors.tri | 30 + programs/every.tri | 148 +++ programs/factorials.tri | 15 + programs/functions.tri | 28 + programs/hi-newcomment.tri | 7 + programs/hi-newcomment2.tri | 11 + programs/hi.tam | Bin 0 -> 112 bytes programs/hi.tri | 3 + programs/hullo.tri | 53 + programs/ifdemo.tri | 9 + programs/increment.tri | 14 + programs/names.tri | 52 + programs/nesting.tri | 31 + programs/procedural.tri | 56 + programs/procedures.tri | 31 + programs/records.tri | 24 + programs/repeatuntil.tri | 14 + programs/repl.tri | 13 + programs/run | 43 + programs/simpleadding.tri | 10 + programs/triangle.tam | Bin 0 -> 1056 bytes programs/triangle.tri | 32 + programs/while-longloop.tri | 22 + programs/while.tri | 11 + settings.gradle | 7 + 202 files changed, 11941 insertions(+) create mode 100644 LICENSE create mode 100644 Triangle.AbstractMachine.Disassembler/.gitignore create mode 100644 Triangle.AbstractMachine.Disassembler/.project create mode 100644 Triangle.AbstractMachine.Disassembler/build.gradle create mode 100644 Triangle.AbstractMachine.Disassembler/pom.xml create mode 100644 Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java create mode 100644 Triangle.AbstractMachine.Interpreter/.gitignore create mode 100644 Triangle.AbstractMachine.Interpreter/.project create mode 100644 Triangle.AbstractMachine.Interpreter/build.gradle create mode 100644 Triangle.AbstractMachine.Interpreter/pom.xml create mode 100644 Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java create mode 100644 Triangle.AbstractMachine/.gitignore create mode 100644 Triangle.AbstractMachine/.project create mode 100644 Triangle.AbstractMachine/build.gradle create mode 100644 Triangle.AbstractMachine/pom.xml create mode 100644 Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java create mode 100644 Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java create mode 100644 Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java create mode 100644 Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java create mode 100644 Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java create mode 100644 Triangle.Compiler/.gitignore create mode 100644 Triangle.Compiler/.project create mode 100644 Triangle.Compiler/build.gradle create mode 100644 Triangle.Compiler/pom.xml create mode 100644 Triangle.Compiler/src/main/java/triangle/Compiler.java create mode 100644 Triangle.Compiler/src/main/java/triangle/ErrorReporter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/StdEnvironment.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java create mode 100644 Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java create mode 100644 Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java create mode 100644 Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java create mode 100644 Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java create mode 100644 Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java create mode 100644 Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java create mode 100644 Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java create mode 100644 Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java create mode 100644 Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java create mode 100644 build.gradle create mode 100644 build/libs/Triangle-Tools.jar create mode 100644 build/tmp/jar/MANIFEST.MF create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 obj.tam create mode 100644 pom.xml create mode 100644 programs/adddeep.tri create mode 100644 programs/arrays.tam create mode 100644 programs/arrays.tri create mode 100644 programs/assignments.tri create mode 100644 programs/bank.tri create mode 100644 programs/bardemo.tri create mode 100644 programs/control.tri create mode 100644 programs/deepnest.tri create mode 100644 programs/directories.tri create mode 100644 programs/errors.tri create mode 100644 programs/every.tri create mode 100644 programs/factorials.tri create mode 100644 programs/functions.tri create mode 100644 programs/hi-newcomment.tri create mode 100644 programs/hi-newcomment2.tri create mode 100644 programs/hi.tam create mode 100644 programs/hi.tri create mode 100644 programs/hullo.tri create mode 100644 programs/ifdemo.tri create mode 100644 programs/increment.tri create mode 100644 programs/names.tri create mode 100644 programs/nesting.tri create mode 100644 programs/procedural.tri create mode 100644 programs/procedures.tri create mode 100644 programs/records.tri create mode 100644 programs/repeatuntil.tri create mode 100644 programs/repl.tri create mode 100755 programs/run create mode 100644 programs/simpleadding.tri create mode 100644 programs/triangle.tam create mode 100644 programs/triangle.tri create mode 100644 programs/while-longloop.tri create mode 100644 programs/while.tri create mode 100644 settings.gradle diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f4c2b81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 deryckb + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Triangle.AbstractMachine.Disassembler/.gitignore b/Triangle.AbstractMachine.Disassembler/.gitignore new file mode 100644 index 0000000..8c107fe --- /dev/null +++ b/Triangle.AbstractMachine.Disassembler/.gitignore @@ -0,0 +1,3 @@ +/target/ +/.classpath +/build/ diff --git a/Triangle.AbstractMachine.Disassembler/.project b/Triangle.AbstractMachine.Disassembler/.project new file mode 100644 index 0000000..7024cd7 --- /dev/null +++ b/Triangle.AbstractMachine.Disassembler/.project @@ -0,0 +1,23 @@ + + + Triangle.AbstractMachine.Disassembler + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/Triangle.AbstractMachine.Disassembler/build.gradle b/Triangle.AbstractMachine.Disassembler/build.gradle new file mode 100644 index 0000000..90e01e7 --- /dev/null +++ b/Triangle.AbstractMachine.Disassembler/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' +apply plugin: 'application' + +sourceCompatibility = 11 + +dependencies { + implementation project(':Triangle.AbstractMachine') +} + +application { + mainClass = 'Triangle.AbstractMachine.Disassembler' +} \ No newline at end of file diff --git a/Triangle.AbstractMachine.Disassembler/pom.xml b/Triangle.AbstractMachine.Disassembler/pom.xml new file mode 100644 index 0000000..847d0fc --- /dev/null +++ b/Triangle.AbstractMachine.Disassembler/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + triangle-disassembler + + triangle.tools + triangle-tools + 2.1 + ../ + + + + triangle.tools + triangle-abstractmachine + 2.1 + + + diff --git a/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java b/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java new file mode 100644 index 0000000..ca94c79 --- /dev/null +++ b/Triangle.AbstractMachine.Disassembler/src/main/java/triangle/abstractMachine/Disassembler.java @@ -0,0 +1,351 @@ +/* + * @(#)Disassembler.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractMachine; + +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Disassembles the TAM code in the given file, and displays the instructions on + * standard output. + * + * For example: + * + *
+ *   java TAM.Disassembler obj.tam
+ * 
+ * + *

+ * Copyright 1991 David A. Watt, University of Glasgow
+ * Copyright 1998 Deryck F. Brown, The Robert Gordon University
+ *

+ * + */ + +public class Disassembler { + + static String objectName; + + static int CT; + + /** + * Writes the r-field of an instruction in the form "lregr", where l and + * r are the bracket characters to use. + * + * @param leftbracket the character to print before the register. + * @param r the number of the register. + * @param rightbracket the character to print after the register. + */ + private static void writeR(char leftbracket, Register r, char rightbracket) { + + System.out.print(leftbracket); + System.out.print(r.toString()); + System.out.print(rightbracket); + } + + private static void writeR(char leftBracket, int r, char rightBracket) { + var register = Register.values()[r]; + writeR(leftBracket, register, rightBracket); + } + + /** + * Writes a void n-field of an instruction. + */ + private static void blankN() { + System.out.print(" "); + } + + // Writes the n-field of an instruction. + /** + * Writes the n-field of an instruction in the form "(n)". + * + * @param n the integer to write. + */ + private static void writeN(int n) { + System.out.print("(" + n + ") "); + if (n < 10) { + System.out.print(" "); + } else if (n < 100) { + System.out.print(" "); + } + } + + /** + * Writes the d-field of an instruction. + * + * @param d the integer to write. + */ + private static void writeD(int d) { + System.out.print(d); + } + + /** + * Writes the name of primitive routine with relative address d. + * + * @param d the displacement of the primitive routine. + */ + private static void writePrimitive(int d) { + var primitive = Primitive.values()[d]; + switch (primitive) { + case ID: + System.out.print("id "); + break; + case NOT: + System.out.print("not "); + break; + case AND: + System.out.print("and "); + break; + case OR: + System.out.print("or "); + break; + case SUCC: + System.out.print("succ "); + break; + case PRED: + System.out.print("pred "); + break; + case NEG: + System.out.print("neg "); + break; + case ADD: + System.out.print("add "); + break; + case SUB: + System.out.print("sub "); + break; + case MULT: + System.out.print("mult "); + break; + case DIV: + System.out.print("div "); + break; + case MOD: + System.out.print("mod "); + break; + case LT: + System.out.print("lt "); + break; + case LE: + System.out.print("le "); + break; + case GE: + System.out.print("ge "); + break; + case GT: + System.out.print("gt "); + break; + case EQ: + System.out.print("eq "); + break; + case NE: + System.out.print("ne "); + break; + case EOL: + System.out.print("eol "); + break; + case EOF: + System.out.print("eof "); + break; + case GET: + System.out.print("get "); + break; + case PUT: + System.out.print("put "); + break; + case GETEOL: + System.out.print("geteol "); + break; + case PUTEOL: + System.out.print("puteol "); + break; + case GETINT: + System.out.print("getint "); + break; + case PUTINT: + System.out.print("putint "); + break; + case NEW: + System.out.print("new "); + break; + case DISPOSE: + System.out.print("dispose "); + break; + } + } + + /** + * Writes the given instruction in assembly-code format. + * + * @param instr the instruction to display. + */ + private static void writeInstruction(Instruction instr) { + + switch (instr.opCode) { + case LOAD: + System.out.print("LOAD "); + writeN(instr.length); + writeD(instr.operand); + writeR('[', instr.register, ']'); + break; + + case LOADA: + System.out.print("LOADA "); + blankN(); + writeD(instr.operand); + writeR('[', instr.register, ']'); + break; + + case LOADI: + System.out.print("LOADI "); + writeN(instr.length); + break; + + case LOADL: + System.out.print("LOADL "); + blankN(); + writeD(instr.operand); + break; + + case STORE: + System.out.print("STORE "); + writeN(instr.length); + writeD(instr.operand); + writeR('[', instr.register, ']'); + break; + + case STOREI: + System.out.print("STOREI"); + writeN(instr.length); + break; + + case CALL: + System.out.print("CALL "); + if (instr.register == Register.PB) { + blankN(); + writePrimitive(instr.operand); + } else { + writeR('(', instr.length, ')'); + System.out.print(" "); + writeD(instr.operand); + writeR('[', instr.register, ']'); + } + break; + + case CALLI: + System.out.print("CALLI "); + break; + + case RETURN: + System.out.print("RETURN"); + writeN(instr.length); + writeD(instr.operand); + break; + + case PUSH: + System.out.print("PUSH "); + blankN(); + writeD(instr.operand); + break; + + case POP: + System.out.print("POP "); + writeN(instr.length); + writeD(instr.operand); + break; + + case JUMP: + System.out.print("JUMP "); + blankN(); + writeD(instr.operand); + writeR('[', instr.register, ']'); + break; + + case JUMPI: + System.out.print("JUMPI "); + break; + + case JUMPIF: + System.out.print("JUMPIF"); + writeN(instr.length); + writeD(instr.operand); + writeR('[', instr.register, ']'); + break; + + case HALT: + System.out.print("HALT "); + } + } + + /** + * Writes all instructions of the program in code store. + */ + private static void disassembleProgram() { + for (int addr = Machine.CB; addr < CT; addr++) { + System.out.print(addr + ": "); + writeInstruction(Machine.code[addr]); + System.out.println(); + } + } + + // LOADING + + /** + * Loads the TAM object program into code store from the named file. + * + * @param objectName the name of the file containing the program. + */ + static void loadObjectProgram(String objectName) { + + var finished = false; + + try (var objectFile = new FileInputStream(objectName)) { + var objectStream = new DataInputStream(objectFile); + var addr = Machine.CB; + while (!finished) { + Machine.code[addr] = Instruction.read(objectStream); + if (Machine.code[addr] == null) { + finished = true; + } else { + addr = addr + 1; + } + } + CT = addr; + } catch (FileNotFoundException s) { + CT = Machine.CB; + System.err.println("Error opening object file: " + s); + } catch (IOException s) { + CT = Machine.CB; + System.err.println("Error reading object file: " + s); + } + } + + // DISASSEMBLE + + public static void main(String[] args) { + System.out.println("********** TAM Disassembler (Sun Version 2.1) **********"); + + if (args.length == 1) { + objectName = args[0]; + } else { + objectName = "obj.tam"; + } + + loadObjectProgram(objectName); + disassembleProgram(); + } +} diff --git a/Triangle.AbstractMachine.Interpreter/.gitignore b/Triangle.AbstractMachine.Interpreter/.gitignore new file mode 100644 index 0000000..8c107fe --- /dev/null +++ b/Triangle.AbstractMachine.Interpreter/.gitignore @@ -0,0 +1,3 @@ +/target/ +/.classpath +/build/ diff --git a/Triangle.AbstractMachine.Interpreter/.project b/Triangle.AbstractMachine.Interpreter/.project new file mode 100644 index 0000000..a22beaa --- /dev/null +++ b/Triangle.AbstractMachine.Interpreter/.project @@ -0,0 +1,23 @@ + + + Triangle.AbstractMachine.Interpreter + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/Triangle.AbstractMachine.Interpreter/build.gradle b/Triangle.AbstractMachine.Interpreter/build.gradle new file mode 100644 index 0000000..38c7835 --- /dev/null +++ b/Triangle.AbstractMachine.Interpreter/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' +apply plugin: 'application' + +sourceCompatibility = 11 + +dependencies { + implementation project(':Triangle.AbstractMachine') +} + +application { + mainClass = 'Triangle.AbstractMachine.Interpreter' +} \ No newline at end of file diff --git a/Triangle.AbstractMachine.Interpreter/pom.xml b/Triangle.AbstractMachine.Interpreter/pom.xml new file mode 100644 index 0000000..551e835 --- /dev/null +++ b/Triangle.AbstractMachine.Interpreter/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + triangle-interpreter + + triangle.tools + triangle-tools + 2.1 + ../ + + + + triangle.tools + triangle-abstractmachine + 2.1 + + + diff --git a/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java b/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java new file mode 100644 index 0000000..96b10c5 --- /dev/null +++ b/Triangle.AbstractMachine.Interpreter/src/main/java/triangle/abstractMachine/Interpreter.java @@ -0,0 +1,645 @@ +/* + * @(#)Interpreter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractMachine; + +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class Interpreter { + + static long startTimeNanos = 0; + + static String objectName; + + // DATA STORE + + static int[] data = new int[1024]; + + // DATA STORE REGISTERS AND OTHER REGISTERS + + final static int CB = 0, SB = 0, HB = 1024; // = upper bound of data array + 1 + + static int CT, CP, ST, HT, LB, status; + + // status values + final static int running = 0, halted = 1, failedDataStoreFull = 2, failedInvalidCodeAddress = 3, + failedInvalidInstruction = 4, failedOverflow = 5, failedZeroDivide = 6, failedIOError = 7; + + static long accumulator; + + static int content(int r) { + var register = Register.values()[r]; + return content(register); + } + + static int content(Register r) { + // Returns the current content of register r, + // even if r is one of the pseudo-registers L1..L6. + + switch (r) { + case CB: + return CB; + case CT: + return CT; + case PB: + return Machine.PB; + case PT: + return Machine.PT; + case SB: + return SB; + case ST: + return ST; + case HB: + return HB; + case HT: + return HT; + case LB: + return LB; + case L1: + return data[LB]; + case L2: + return data[data[LB]]; + case L3: + return data[data[data[LB]]]; + case L4: + return data[data[data[data[LB]]]]; + case L5: + return data[data[data[data[data[LB]]]]]; + case L6: + return data[data[data[data[data[data[LB]]]]]]; + case CP: + return CP; + default: + return 0; + } + } + + // PROGRAM STATUS + + static void dump() { + // Writes a summary of the machine state. + + System.out.println(""); + System.out.println("State of data store and registers:"); + System.out.println(""); + if (HT == HB) { + System.out.println(" |--------| (heap is empty)"); + } else { + System.out.println(" HB-->"); + System.out.println(" |--------|"); + for (var addr = HB - 1; addr >= HT; addr--) { + System.out.print(addr + ":"); + if (addr == HT) { + System.out.print(" HT-->"); + } else { + System.out.print(" "); + } + System.out.println("|" + data[addr] + "|"); + } + System.out.println(" |--------|"); + } + System.out.println(" |////////|"); + System.out.println(" |////////|"); + if (ST == SB) { + System.out.println(" |--------| (stack is empty)"); + } else { + var dynamicLink = LB; + var staticLink = LB; + var localRegNum = Register.LB; + System.out.println(" ST--> |////////|"); + System.out.println(" |--------|"); + for (var addr = ST - 1; addr >= SB; addr--) { + System.out.print(addr + ":"); + if (addr == SB) { + System.out.print(" SB-->"); + } else if (addr == staticLink) { + switch (localRegNum) { + case LB: + System.out.print(" LB-->"); + break; + case L1: + System.out.print(" L1-->"); + break; + case L2: + System.out.print(" L2-->"); + break; + case L3: + System.out.print(" L3-->"); + break; + case L4: + System.out.print(" L4-->"); + break; + case L5: + System.out.print(" L5-->"); + break; + case L6: + System.out.print(" L6-->"); + break; + default: + break; + } + staticLink = data[addr]; + localRegNum = Register.values()[localRegNum.ordinal() + 1]; + } else { + System.out.print(" "); + } + if (addr == dynamicLink && dynamicLink != SB) { + System.out.print("|SL=" + data[addr] + "|"); + } else if (addr == dynamicLink + 1 && dynamicLink != SB) { + System.out.print("|DL=" + data[addr] + "|"); + } else if (addr == dynamicLink + 2 && dynamicLink != SB) { + System.out.print("|RA=" + data[addr] + "|"); + } else { + System.out.print("|" + data[addr] + "|"); + } + System.out.println(""); + if (addr == dynamicLink) { + System.out.println(" |--------|"); + dynamicLink = data[addr + 1]; + } + } + } + System.out.println(""); + } + + static void showStatus() { + // Writes an indication of whether and why the program has terminated. + System.out.println(""); + switch (status) { + case running: + System.out.println("Program is running."); + break; + case halted: + System.out.println("Program has halted normally."); + System.out.println("Total execution time (ns): " + (System.nanoTime() - startTimeNanos)); + break; + case failedDataStoreFull: + System.out.println("Program has failed due to exhaustion of Data Store."); + break; + case failedInvalidCodeAddress: + System.out.println("Program has failed due to an invalid code address."); + break; + case failedInvalidInstruction: + System.out.println("Program has failed due to an invalid instruction."); + break; + case failedOverflow: + System.out.println("Program has failed due to overflow."); + break; + case failedZeroDivide: + System.out.println("Program has failed due to division by zero."); + break; + case failedIOError: + System.out.println("Program has failed due to an IO error."); + break; + } + if (status != halted) { + dump(); + } + } + + // INTERPRETATION + + static void checkSpace(int spaceNeeded) { + // Signals failure if there is not enough space to expand the stack or + // heap by spaceNeeded. + + if (HT - ST < spaceNeeded) { + status = failedDataStoreFull; + } + } + + static boolean isTrue(int datum) { + // Tests whether the given datum represents true. + return (datum == Machine.trueRep); + } + + static boolean equal(int size, int addr1, int addr2) { + // Tests whether two multi-word objects are equal, given their common + // size and their base addresses. + + boolean eq; + int index; + + eq = true; + index = 0; + while (eq && (index < size)) { + if (data[addr1 + index] == data[addr2 + index]) { + index = index + 1; + } else { + eq = false; + } + } + + return eq; + } + + static int overflowChecked(long datum) { + // Signals failure if the datum is too large to fit into a single word, + // otherwise returns the datum as a single word. + + if ((-Machine.maxintRep <= datum) && (datum <= Machine.maxintRep)) { + return (int) datum; + } else { + status = failedOverflow; + return 0; + } + } + + static int toInt(boolean b) { + return b ? Machine.trueRep : Machine.falseRep; + } + + static int currentChar; + + static int readInt() throws java.io.IOException { + int temp = 0; + int sign = 1; + + do { + currentChar = System.in.read(); + } while (Character.isWhitespace((char) currentChar)); + + if ((currentChar == '-') || (currentChar == '+')) { + do { + sign = (currentChar == '-') ? -1 : 1; + currentChar = System.in.read(); + } while ((currentChar == '-') || currentChar == '+'); + } + + if (Character.isDigit((char) currentChar)) { + do { + temp = temp * 10 + (currentChar - '0'); + currentChar = System.in.read(); + } while (Character.isDigit((char) currentChar)); + } + + return sign * temp; + } + + static void callPrimitive(int primitiveDisplacement) { + // Invokes the given primitive routine. + + int addr, size; + char ch; + + var primitive = Primitive.values()[primitiveDisplacement]; + switch (primitive) { + case ID: + break; // nothing to be done + case NOT: + data[ST - 1] = toInt(!isTrue(data[ST - 1])); + break; + case AND: + ST = ST - 1; + data[ST - 1] = toInt(isTrue(data[ST - 1]) & isTrue(data[ST])); + break; + case OR: + ST = ST - 1; + data[ST - 1] = toInt(isTrue(data[ST - 1]) | isTrue(data[ST])); + break; + case SUCC: + data[ST - 1] = overflowChecked(data[ST - 1] + 1); + break; + case PRED: + data[ST - 1] = overflowChecked(data[ST - 1] - 1); + break; + case NEG: + data[ST - 1] = -data[ST - 1]; + break; + case ADD: + ST = ST - 1; + accumulator = data[ST - 1]; + data[ST - 1] = overflowChecked(accumulator + data[ST]); + break; + case SUB: + ST = ST - 1; + accumulator = data[ST - 1]; + data[ST - 1] = overflowChecked(accumulator - data[ST]); + break; + case MULT: + ST = ST - 1; + accumulator = data[ST - 1]; + data[ST - 1] = overflowChecked(accumulator * data[ST]); + break; + case DIV: + ST = ST - 1; + accumulator = data[ST - 1]; + if (data[ST] != 0) { + data[ST - 1] = (int) (accumulator / data[ST]); + } else { + status = failedZeroDivide; + } + break; + case MOD: + ST = ST - 1; + accumulator = data[ST - 1]; + if (data[ST] != 0) { + data[ST - 1] = (int) (accumulator % data[ST]); + } else { + status = failedZeroDivide; + } + break; + case LT: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] < data[ST]); + break; + case LE: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] <= data[ST]); + break; + case GE: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] >= data[ST]); + break; + case GT: + ST = ST - 1; + data[ST - 1] = toInt(data[ST - 1] > data[ST]); + break; + case EQ: + size = data[ST - 1]; // size of each comparand + ST = ST - 2 * size; + data[ST - 1] = toInt(equal(size, ST - 1, ST - 1 + size)); + break; + case NE: + size = data[ST - 1]; // size of each comparand + ST = ST - 2 * size; + data[ST - 1] = toInt(!equal(size, ST - 1, ST - 1 + size)); + break; + case EOL: + data[ST] = toInt(currentChar == '\n'); + ST = ST + 1; + break; + case EOF: + data[ST] = toInt(currentChar == -1); + ST = ST + 1; + break; + case GET: + ST = ST - 1; + addr = data[ST]; + try { + currentChar = System.in.read(); + } catch (java.io.IOException s) { + status = failedIOError; + } + data[addr] = currentChar; + break; + case PUT: + ST = ST - 1; + ch = (char) data[ST]; + System.out.print(ch); + break; + case GETEOL: + try { + while ((currentChar = System.in.read()) != '\n') + ; + } catch (java.io.IOException s) { + status = failedIOError; + } + break; + case PUTEOL: + System.out.println(""); + break; + case GETINT: + ST = ST - 1; + addr = data[ST]; + try { + accumulator = readInt(); + } catch (java.io.IOException s) { + status = failedIOError; + } + data[addr] = (int) accumulator; + break; + case PUTINT: + ST = ST - 1; + accumulator = data[ST]; + System.out.print(accumulator); + break; + case NEW: + size = data[ST - 1]; + checkSpace(size); + HT = HT - size; + data[ST - 1] = HT; + break; + case DISPOSE: + ST = ST - 1; // no action taken at present + break; + } + } + + static void interpretProgram() { + // Runs the program in code store. + + Instruction currentInstr; + + // Initialize registers ... + ST = SB; + HT = HB; + LB = SB; + CP = CB; + status = running; + do { + // Fetch instruction ... + currentInstr = Machine.code[CP]; + // Decode instruction ... + var op = currentInstr.opCode; + var r = currentInstr.register; + var n = currentInstr.length; + var d = currentInstr.operand; + int addr; + + // Execute instruction ... + switch (op) { + case LOAD: + addr = d + content(r); + checkSpace(n); + for (var index = 0; index < n; index++) { + data[ST + index] = data[addr + index]; + } + ST = ST + n; + CP = CP + 1; + break; + case LOADA: + addr = d + content(r); + checkSpace(1); + data[ST] = addr; + ST = ST + 1; + CP = CP + 1; + break; + case LOADI: + ST = ST - 1; + addr = data[ST]; + checkSpace(n); + for (var index = 0; index < n; index++) { + data[ST + index] = data[addr + index]; + } + ST = ST + n; + CP = CP + 1; + break; + case LOADL: + checkSpace(1); + data[ST] = d; + ST = ST + 1; + CP = CP + 1; + break; + case STORE: + addr = d + content(r); + ST = ST - n; + for (var index = 0; index < n; index++) { + data[addr + index] = data[ST + index]; + } + CP = CP + 1; + break; + case STOREI: + ST = ST - 1; + addr = data[ST]; + ST = ST - n; + for (var index = 0; index < n; index++) { + data[addr + index] = data[ST + index]; + } + CP = CP + 1; + break; + case CALL: + addr = d + content(r); + if (addr >= Machine.PB) { + callPrimitive(addr - Machine.PB); + CP = CP + 1; + } else { + checkSpace(3); + if (0 <= n && n <= 15) { + data[ST] = content(n); // static link + } else { + status = failedInvalidInstruction; + } + data[ST + 1] = LB; // dynamic link + data[ST + 2] = CP + 1; // return address + LB = ST; + ST = ST + 3; + CP = addr; + } + break; + case CALLI: + ST = ST - 2; + addr = data[ST + 1]; + if (addr >= Machine.PB) { + callPrimitive(addr - Machine.PB); + CP = CP + 1; + } else { + // data[ST] = static link already + data[ST + 1] = LB; // dynamic link + data[ST + 2] = CP + 1; // return address + LB = ST; + ST = ST + 3; + CP = addr; + } + break; + case RETURN: + addr = LB - d; + CP = data[LB + 2]; + LB = data[LB + 1]; + ST = ST - n; + for (var index = 0; index < n; index++) { + data[addr + index] = data[ST + index]; + } + ST = addr + n; + break; + case PUSH: + checkSpace(d); + ST = ST + d; + CP = CP + 1; + break; + case POP: + addr = ST - n - d; + ST = ST - n; + for (var index = 0; index < n; index++) { + data[addr + index] = data[ST + index]; + } + ST = addr + n; + CP = CP + 1; + break; + case JUMP: + CP = d + content(r); + break; + case JUMPI: + ST = ST - 1; + CP = data[ST]; + break; + case JUMPIF: + ST = ST - 1; + if (data[ST] == n) { + CP = d + content(r); + } else { + CP = CP + 1; + } + break; + case HALT: + status = halted; + break; + } + if (CP < CB || CP >= CT) { + status = failedInvalidCodeAddress; + } + } while (status == running); + } + + // LOADING + + static void loadObjectProgram(String objectName) { + // Loads the TAM object program into code store from the named file. + + boolean finished = false; + + try (var objectFile = new FileInputStream(objectName)) { + var objectStream = new DataInputStream(objectFile); + + var addr = Machine.CB; + while (!finished) { + Machine.code[addr] = Instruction.read(objectStream); + if (Machine.code[addr] == null) { + finished = true; + } else { + addr = addr + 1; + } + } + CT = addr; + } catch (FileNotFoundException s) { + CT = CB; + System.err.println("Error opening object file: " + s); + } catch (IOException s) { + CT = CB; + System.err.println("Error reading object file: " + s); + } + } + + // RUNNING + + public static void main(String[] args) { + System.out.println("********** TAM Interpreter (Java Version 2.1) **********"); + + if (args.length == 1) { + objectName = args[0]; + } else { + objectName = "obj.tam"; + } + + loadObjectProgram(objectName); + if (CT != CB) { + startTimeNanos = System.nanoTime(); + interpretProgram(); + showStatus(); + } + } +} diff --git a/Triangle.AbstractMachine/.gitignore b/Triangle.AbstractMachine/.gitignore new file mode 100644 index 0000000..8c107fe --- /dev/null +++ b/Triangle.AbstractMachine/.gitignore @@ -0,0 +1,3 @@ +/target/ +/.classpath +/build/ diff --git a/Triangle.AbstractMachine/.project b/Triangle.AbstractMachine/.project new file mode 100644 index 0000000..42358c2 --- /dev/null +++ b/Triangle.AbstractMachine/.project @@ -0,0 +1,23 @@ + + + Triangle.AbstractMachine + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/Triangle.AbstractMachine/build.gradle b/Triangle.AbstractMachine/build.gradle new file mode 100644 index 0000000..80f98eb --- /dev/null +++ b/Triangle.AbstractMachine/build.gradle @@ -0,0 +1,4 @@ +apply plugin: 'java-library' +apply plugin: 'eclipse' + +sourceCompatibility = 11 \ No newline at end of file diff --git a/Triangle.AbstractMachine/pom.xml b/Triangle.AbstractMachine/pom.xml new file mode 100644 index 0000000..c7675fa --- /dev/null +++ b/Triangle.AbstractMachine/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + triangle-abstractmachine + jar + + triangle.tools + triangle-tools + 2.1 + ../ + + \ No newline at end of file diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java new file mode 100644 index 0000000..7ca85c9 --- /dev/null +++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Instruction.java @@ -0,0 +1,67 @@ +/* + * @(#)Instruction.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractMachine; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.IOException; + +public class Instruction { + + // Java has no type synonyms, so the following representations are + // assumed: + // + // type + // OpCode = 0..15; {4 bits unsigned} + // Length = 0..255; {8 bits unsigned} + // Operand = -32767..+32767; {16 bits signed} + + // Represents TAM instructions. + final OpCode opCode; + final Register register; + final int length; + int operand; // Not final to allow for patching jump address + + public Instruction(OpCode opcode, Register register, int length, int operand) { + this.opCode = opcode; + this.register = register; + this.length = length; + this.operand = operand; + } + + public void setOperand(int operand) { + this.operand = operand; + } + + public void write(DataOutputStream output) throws IOException { + output.writeInt(opCode.ordinal()); + output.writeInt(register.ordinal()); + output.writeInt(length); + output.writeInt(operand); + } + + public static Instruction read(DataInputStream input) throws IOException { + try { + var opCode = OpCode.values()[input.readInt()]; + var register = Register.values()[input.readInt()]; + var length = input.readInt(); + var operand = input.readInt(); + return new Instruction(opCode, register, length, operand); + } catch (EOFException s) { + return null; + } + } +} diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java new file mode 100644 index 0000000..c857fa5 --- /dev/null +++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Machine.java @@ -0,0 +1,54 @@ +/* + * @(#)Machine.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractMachine; + +public final class Machine { + + public final static int maxRoutineLevel = 7; + + // WORDS AND ADDRESSES + + // Java has no type synonyms, so the following representations are + // assumed: + // + // type + // Word = -32767..+32767; {16 bits signed} + // DoubleWord = -2147483648..+2147483647; {32 bits signed} + // CodeAddress = 0..+32767; {15 bits unsigned} + // DataAddress = 0..+32767; {15 bits unsigned} + + // INSTRUCTIONS + + // CODE STORE + + public static Instruction[] code = new Instruction[1024]; + + // CODE STORE REGISTERS + + public final static int CB = 0, PB = 1024, // = upper bound of code array + 1 + PT = 1052; // = PB + 28 + + // REGISTER NUMBERS + + // DATA REPRESENTATION + + public final static int booleanSize = 1, characterSize = 1, integerSize = 1, addressSize = 1, + closureSize = 2 * addressSize, + + linkDataSize = 3 * addressSize, + + falseRep = 0, trueRep = 1, maxintRep = 32767; + +} diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java new file mode 100644 index 0000000..23ca257 --- /dev/null +++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/OpCode.java @@ -0,0 +1,5 @@ +package triangle.abstractMachine; + +public enum OpCode { + LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, CALLI, RETURN, NOP, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT +} diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java new file mode 100644 index 0000000..11bb5bc --- /dev/null +++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Primitive.java @@ -0,0 +1,6 @@ +package triangle.abstractMachine; + +public enum Primitive { + ID, NOT, AND, OR, SUCC, PRED, NEG, ADD, SUB, MULT, DIV, MOD, LT, LE, GE, GT, EQ, NE, EOL, EOF, GET, PUT, GETEOL, + PUTEOL, GETINT, PUTINT, NEW, DISPOSE +} diff --git a/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java new file mode 100644 index 0000000..0b36262 --- /dev/null +++ b/Triangle.AbstractMachine/src/main/java/triangle/abstractMachine/Register.java @@ -0,0 +1,5 @@ +package triangle.abstractMachine; + +public enum Register { + CB, CT, PB, PT, SB, ST, HB, HT, LB, L1, L2, L3, L4, L5, L6, CP +} diff --git a/Triangle.Compiler/.gitignore b/Triangle.Compiler/.gitignore new file mode 100644 index 0000000..55f062a --- /dev/null +++ b/Triangle.Compiler/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.classpath +/.editorconfig +/build/ diff --git a/Triangle.Compiler/.project b/Triangle.Compiler/.project new file mode 100644 index 0000000..dca5b8c --- /dev/null +++ b/Triangle.Compiler/.project @@ -0,0 +1,23 @@ + + + Triangle.Compiler + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/Triangle.Compiler/build.gradle b/Triangle.Compiler/build.gradle new file mode 100644 index 0000000..9733b3f --- /dev/null +++ b/Triangle.Compiler/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'java' +apply plugin: 'application' + +sourceCompatibility = 11 + +repositories { + mavenCentral() +} + + +dependencies { + implementation project(':Triangle.AbstractMachine') + testImplementation group: 'junit', name: 'junit', version: '4.13.2' +} + +application { + mainClass = 'Triangle.Compiler' +} + +// allow access to programs for unit tests +sourceSets.test.resources.srcDir file("$rootDir/programs") \ No newline at end of file diff --git a/Triangle.Compiler/pom.xml b/Triangle.Compiler/pom.xml new file mode 100644 index 0000000..17b97da --- /dev/null +++ b/Triangle.Compiler/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + triangle-compiler + + triangle.tools + triangle-tools + 2.1 + ../ + + + + triangle.tools + triangle-abstractmachine + 2.1 + + + diff --git a/Triangle.Compiler/src/main/java/triangle/Compiler.java b/Triangle.Compiler/src/main/java/triangle/Compiler.java new file mode 100644 index 0000000..1a49778 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/Compiler.java @@ -0,0 +1,152 @@ +/* + * @(#)Compiler.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle; + +import triangle.abstractSyntaxTrees.Program; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Encoder; +import triangle.contextualAnalyzer.Checker; +import triangle.optimiser.ConstantFolder; +import triangle.syntacticAnalyzer.Parser; +import triangle.syntacticAnalyzer.Scanner; +import triangle.syntacticAnalyzer.SourceFile; +import triangle.treeDrawer.Drawer; + +/** + * The main driver class for the Triangle compiler. + * + * @version 2.1 7 Oct 2003 + * @author Deryck F. Brown + */ +public class Compiler { + + /** The filename for the object program, normally obj.tam. */ + static String objectName = "obj.tam"; + + static boolean showTree = false; + static boolean folding = false; + + private static Scanner scanner; + private static Parser parser; + private static Checker checker; + private static Encoder encoder; + private static Emitter emitter; + private static ErrorReporter reporter; + private static Drawer drawer; + + /** The AST representing the source program. */ + private static Program theAST; + + /** + * Compile the source program to TAM machine code. + * + * @param sourceName the name of the file containing the source program. + * @param objectName the name of the file containing the object program. + * @param showingAST true iff the AST is to be displayed after contextual + * analysis + * @param showingTable true iff the object description details are to be + * displayed during code generation (not currently + * implemented). + * @return true iff the source program is free of compile-time errors, otherwise + * false. + */ + static boolean compileProgram(String sourceName, String objectName, boolean showingAST, boolean showingTable) { + + System.out.println("********** " + "Triangle Compiler (Java Version 2.1)" + " **********"); + + System.out.println("Syntactic Analysis ..."); + SourceFile source = SourceFile.ofPath(sourceName); + + if (source == null) { + System.out.println("Can't access source file " + sourceName); + System.exit(1); + } + + scanner = new Scanner(source); + reporter = new ErrorReporter(false); + parser = new Parser(scanner, reporter); + checker = new Checker(reporter); + emitter = new Emitter(reporter); + encoder = new Encoder(emitter, reporter); + drawer = new Drawer(); + + // scanner.enableDebugging(); + theAST = parser.parseProgram(); // 1st pass + if (reporter.getNumErrors() == 0) { + // if (showingAST) { + // drawer.draw(theAST); + // } + System.out.println("Contextual Analysis ..."); + checker.check(theAST); // 2nd pass + if (showingAST) { + drawer.draw(theAST); + } + if (folding) { + theAST.visit(new ConstantFolder()); + } + + if (reporter.getNumErrors() == 0) { + System.out.println("Code Generation ..."); + encoder.encodeRun(theAST, showingTable); // 3rd pass + } + } + + boolean successful = (reporter.getNumErrors() == 0); + if (successful) { + emitter.saveObjectProgram(objectName); + System.out.println("Compilation was successful."); + } else { + System.out.println("Compilation was unsuccessful."); + } + return successful; + } + + /** + * Triangle compiler main program. + * + * @param args the only command-line argument to the program specifies the + * source filename. + */ + public static void main(String[] args) { + + if (args.length < 1) { + System.out.println("Usage: tc filename [-o=outputfilename] [tree] [folding]"); + System.exit(1); + } + + parseArgs(args); + + String sourceName = args[0]; + + var compiledOK = compileProgram(sourceName, objectName, showTree, false); + + if (!showTree) { + System.exit(compiledOK ? 0 : 1); + } + } + + private static void parseArgs(String[] args) { + for (String s : args) { + var sl = s.toLowerCase(); + if (sl.equals("tree")) { + showTree = true; + } else if (sl.startsWith("-o=")) { + objectName = s.substring(3); + } else if (sl.equals("folding")) { + folding = true; + } + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java b/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java new file mode 100644 index 0000000..cfcc753 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/ErrorReporter.java @@ -0,0 +1,61 @@ +/* + * @(#)ErrorReporter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle; + +import triangle.syntacticAnalyzer.SourcePosition; + +public class ErrorReporter { + + private int numErrors; + + private boolean throwExceptions; + + /** + * @param throwExceptions if true, throw exceptions (good for unit tests) otherwise write to stdout + */ + public ErrorReporter(boolean throwExceptions) { + numErrors = 0; + this.throwExceptions = throwExceptions; + } + + public void reportError(String message, String tokenName, SourcePosition pos) { + + numErrors++; + + String s = ("ERROR: "); + + for (int p = 0; p < message.length(); p++) + if (message.charAt(p) == '%') + s += tokenName; + else + s += message.charAt(p); + s += (" " + pos.start + ".." + pos.finish); + + if (throwExceptions) { + throw new RuntimeException(s); + } else { + System.out.println(s); + } + + } + + public void reportRestriction(String message) { + System.out.println("RESTRICTION: " + message); + } + + public int getNumErrors() { + return numErrors; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java b/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java new file mode 100644 index 0000000..90507d0 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/StdEnvironment.java @@ -0,0 +1,46 @@ +/* + * @(#)StdEnvironment.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle; + +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.types.TypeDenoter; + +public final class StdEnvironment { + + // These are small ASTs representing standard types. + + public static TypeDenoter booleanType, charType, integerType, anyType, errorType; + + public static TypeDeclaration booleanDecl, charDecl, integerDecl; + + // These are small ASTs representing "declarations" of standard entities. + + public static ConstDeclaration falseDecl, trueDecl, maxintDecl; + + public static UnaryOperatorDeclaration notDecl; + + public static BinaryOperatorDeclaration andDecl, orDecl, addDecl, subtractDecl, multiplyDecl, divideDecl, + moduloDecl, equalDecl, unequalDecl, lessDecl, notlessDecl, greaterDecl, notgreaterDecl; + + public static ProcDeclaration getDecl, putDecl, getintDecl, putintDecl, geteolDecl, puteolDecl; + + public static FuncDeclaration chrDecl, ordDecl, eolDecl, eofDecl; + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java new file mode 100644 index 0000000..669f768 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/AbstractSyntaxTree.java @@ -0,0 +1,34 @@ +/* + * @(#)AST.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees; + +import triangle.codeGenerator.entities.RuntimeEntity; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class AbstractSyntaxTree { + + private final SourcePosition position; + + public AbstractSyntaxTree(SourcePosition position) { + this.position = position; + entity = null; + } + + public SourcePosition getPosition() { + return position; + } + + public RuntimeEntity entity; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java new file mode 100644 index 0000000..17a0aa8 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/Program.java @@ -0,0 +1,37 @@ +/* + * @(#)Program.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees; + +import triangle.abstractSyntaxTrees.commands.Command; +import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class Program extends AbstractSyntaxTree { + + public Program(Command cAST, SourcePosition position) { + super(position); + C = cAST; + } + + public Command C; + + public TResult visit(ProgramVisitor visitor, TArg arg) { + return visitor.visitProgram(this, arg); + } + + public TResult visit(ProgramVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java new file mode 100644 index 0000000..73188df --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameter.java @@ -0,0 +1,32 @@ +/* + * @(#)ActualParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class ActualParameter extends AbstractSyntaxTree { + + public ActualParameter(SourcePosition position) { + super(position); + } + + public abstract TResult visit(ActualParameterVisitor visitor, TArg arg); + + public TResult visit(ActualParameterVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java new file mode 100644 index 0000000..d5a2c9a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ActualParameterSequence.java @@ -0,0 +1,32 @@ +/* + * @(#)ActualParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class ActualParameterSequence extends AbstractSyntaxTree { + + public ActualParameterSequence(SourcePosition position) { + super(position); + } + + public abstract TResult visit(ActualParameterSequenceVisitor v, TArg arg); + + public TResult visit(ActualParameterSequenceVisitor v) { + return visit(v, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java new file mode 100644 index 0000000..ad469dc --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ConstActualParameter.java @@ -0,0 +1,33 @@ +/* + * @(#)ConstActualParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ConstActualParameter extends ActualParameter { + + public ConstActualParameter(Expression eAST, SourcePosition position) { + super(position); + E = eAST; + } + + public TResult visit(ActualParameterVisitor v, TArg arg) { + return v.visitConstActualParameter(this, arg); + } + + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java new file mode 100644 index 0000000..13fa735 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/EmptyActualParameterSequence.java @@ -0,0 +1,29 @@ +/* + * @(#)EmptyActualParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class EmptyActualParameterSequence extends ActualParameterSequence { + + public EmptyActualParameterSequence(SourcePosition position) { + super(position); + } + + public TResult visit(ActualParameterSequenceVisitor v, TArg arg) { + return v.visitEmptyActualParameterSequence(this, arg); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java new file mode 100644 index 0000000..3aa0430 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/FuncActualParameter.java @@ -0,0 +1,33 @@ +/* + * @(#)FuncActualParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class FuncActualParameter extends ActualParameter { + + public FuncActualParameter(Identifier iAST, SourcePosition position) { + super(position); + I = iAST; + } + + public TResult visit(ActualParameterVisitor v, TArg arg) { + return v.visitFuncActualParameter(this, arg); + } + + public final Identifier I; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java new file mode 100644 index 0000000..91e53ef --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/MultipleActualParameterSequence.java @@ -0,0 +1,35 @@ +/* + * @(#)MultipleActualParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class MultipleActualParameterSequence extends ActualParameterSequence { + + public MultipleActualParameterSequence(ActualParameter apAST, ActualParameterSequence apsAST, + SourcePosition position) { + super(position); + AP = apAST; + APS = apsAST; + } + + public TResult visit(ActualParameterSequenceVisitor v, TArg arg) { + return v.visitMultipleActualParameterSequence(this, arg); + } + + public final ActualParameter AP; + public final ActualParameterSequence APS; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java new file mode 100644 index 0000000..83c40c7 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/ProcActualParameter.java @@ -0,0 +1,33 @@ +/* + * @(#)ProcActualParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ProcActualParameter extends ActualParameter { + + public ProcActualParameter(Identifier iAST, SourcePosition position) { + super(position); + I = iAST; + } + + public TResult visit(ActualParameterVisitor v, TArg arg) { + return v.visitProcActualParameter(this, arg); + } + + public final Identifier I; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java new file mode 100644 index 0000000..4dd3a89 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/SingleActualParameterSequence.java @@ -0,0 +1,32 @@ +/* + * @(#)SingleActualParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SingleActualParameterSequence extends ActualParameterSequence { + + public SingleActualParameterSequence(ActualParameter apAST, SourcePosition position) { + super(position); + AP = apAST; + } + + public TResult visit(ActualParameterSequenceVisitor v, TArg arg) { + return v.visitSingleActualParameterSequence(this, arg); + } + + public final ActualParameter AP; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java new file mode 100644 index 0000000..979dd15 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/actuals/VarActualParameter.java @@ -0,0 +1,33 @@ +/* + * @(#)VarActualParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.actuals; + +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.syntacticAnalyzer.SourcePosition; + +public class VarActualParameter extends ActualParameter { + + public VarActualParameter(Vname vAST, SourcePosition position) { + super(position); + V = vAST; + } + + public TResult visit(ActualParameterVisitor v, TArg arg) { + return v.visitVarActualParameter(this, arg); + } + + public final Vname V; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java new file mode 100644 index 0000000..e90330b --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/ArrayAggregate.java @@ -0,0 +1,35 @@ +/* + * @(#)ArrayAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class ArrayAggregate extends AbstractSyntaxTree { + + public ArrayAggregate(SourcePosition position) { + super(position); + elemCount = 0; + } + + public int elemCount; + + public abstract TResult visit(ArrayAggregateVisitor visitor, TArg arg); + + public TResult visit(ArrayAggregateVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java new file mode 100644 index 0000000..5b616e1 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleArrayAggregate.java @@ -0,0 +1,35 @@ +/* + * @(#)MultipleArrayAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class MultipleArrayAggregate extends ArrayAggregate { + + public MultipleArrayAggregate(Expression eAST, ArrayAggregate aaAST, SourcePosition position) { + super(position); + E = eAST; + AA = aaAST; + } + + public TResult visit(ArrayAggregateVisitor v, TArg arg) { + return v.visitMultipleArrayAggregate(this, arg); + } + + public Expression E; + public final ArrayAggregate AA; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java new file mode 100644 index 0000000..1715b2e --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/MultipleRecordAggregate.java @@ -0,0 +1,38 @@ +/* + * @(#)MultipleRecordAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class MultipleRecordAggregate extends RecordAggregate { + + public MultipleRecordAggregate(Identifier iAST, Expression eAST, RecordAggregate raAST, SourcePosition position) { + super(position); + I = iAST; + E = eAST; + RA = raAST; + } + + public TResult visit(RecordAggregateVisitor v, TArg arg) { + return v.visitMultipleRecordAggregate(this, arg); + } + + public final Identifier I; + public Expression E; + public final RecordAggregate RA; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java new file mode 100644 index 0000000..f79bd9c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/RecordAggregate.java @@ -0,0 +1,36 @@ +/* + * @(#)RecordAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.types.FieldTypeDenoter; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class RecordAggregate extends AbstractSyntaxTree { + + public RecordAggregate(SourcePosition position) { + super(position); + type = null; + } + + public FieldTypeDenoter type; + + public abstract TResult visit(RecordAggregateVisitor visitor, TArg arg); + + public TResult visit(RecordAggregateVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java new file mode 100644 index 0000000..4d5c624 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleArrayAggregate.java @@ -0,0 +1,33 @@ +/* + * @(#)SingleArrayAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SingleArrayAggregate extends ArrayAggregate { + + public SingleArrayAggregate(Expression eAST, SourcePosition position) { + super(position); + E = eAST; + } + + public TResult visit(ArrayAggregateVisitor v, TArg arg) { + return v.visitSingleArrayAggregate(this, arg); + } + + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java new file mode 100644 index 0000000..14510c9 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/aggregates/SingleRecordAggregate.java @@ -0,0 +1,36 @@ +/* + * @(#)SingleRecordAggregate.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.aggregates; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SingleRecordAggregate extends RecordAggregate { + + public SingleRecordAggregate(Identifier iAST, Expression eAST, SourcePosition position) { + super(position); + I = iAST; + E = eAST; + } + + public TResult visit(RecordAggregateVisitor v, TArg arg) { + return v.visitSingleRecordAggregate(this, arg); + } + + public final Identifier I; + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java new file mode 100644 index 0000000..66906ae --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/AssignCommand.java @@ -0,0 +1,36 @@ +/* + * @(#)AssignCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.syntacticAnalyzer.SourcePosition; + +public class AssignCommand extends Command { + + public AssignCommand(Vname vAST, Expression eAST, SourcePosition position) { + super(position); + V = vAST; + E = eAST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitAssignCommand(this, arg); + } + + public final Vname V; + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java new file mode 100644 index 0000000..40da558 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/CallCommand.java @@ -0,0 +1,36 @@ +/* + * @(#)CallCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class CallCommand extends Command { + + public CallCommand(Identifier iAST, ActualParameterSequence apsAST, SourcePosition position) { + super(position); + I = iAST; + APS = apsAST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitCallCommand(this, arg); + } + + public final Identifier I; + public final ActualParameterSequence APS; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java new file mode 100644 index 0000000..cd9b94d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/Command.java @@ -0,0 +1,32 @@ +/* + * @(#)Command.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class Command extends AbstractSyntaxTree { + + public Command(SourcePosition position) { + super(position); + } + + public abstract TResult visit(CommandVisitor visitor, TArg arg); + + public TResult visit(CommandVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java new file mode 100644 index 0000000..df0a2fb --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/EmptyCommand.java @@ -0,0 +1,29 @@ +/* + * @(#)EmptyCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class EmptyCommand extends Command { + + public EmptyCommand(SourcePosition position) { + super(position); + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitEmptyCommand(this, arg); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java new file mode 100644 index 0000000..e57d560 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/IfCommand.java @@ -0,0 +1,36 @@ +/* + * @(#)IfCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class IfCommand extends Command { + + public IfCommand(Expression eAST, Command c1AST, Command c2AST, SourcePosition position) { + super(position); + E = eAST; + C1 = c1AST; + C2 = c2AST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitIfCommand(this, arg); + } + + public Expression E; + public final Command C1, C2; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java new file mode 100644 index 0000000..f59cc5c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/LetCommand.java @@ -0,0 +1,35 @@ +/* + * @(#)LetCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class LetCommand extends Command { + + public LetCommand(Declaration dAST, Command cAST, SourcePosition position) { + super(position); + D = dAST; + C = cAST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitLetCommand(this, arg); + } + + public final Declaration D; + public final Command C; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java new file mode 100644 index 0000000..f8f5f21 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/SequentialCommand.java @@ -0,0 +1,33 @@ +/* + * @(#)SequentialCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SequentialCommand extends Command { + + public SequentialCommand(Command c1AST, Command c2AST, SourcePosition position) { + super(position); + C1 = c1AST; + C2 = c2AST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitSequentialCommand(this, arg); + } + + public final Command C1, C2; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java new file mode 100644 index 0000000..af21fde --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/commands/WhileCommand.java @@ -0,0 +1,35 @@ +/* + * @(#)WhileCommand.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.commands; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class WhileCommand extends Command { + + public WhileCommand(Expression eAST, Command cAST, SourcePosition position) { + super(position); + E = eAST; + C = cAST; + } + + public TResult visit(CommandVisitor v, TArg arg) { + return v.visitWhileCommand(this, arg); + } + + public Expression E; + public final Command C; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java new file mode 100644 index 0000000..1a1b524 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/BinaryOperatorDeclaration.java @@ -0,0 +1,39 @@ +/* + * @(#)BinaryOperatorDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class BinaryOperatorDeclaration extends Declaration { + + public BinaryOperatorDeclaration(Operator oAST, TypeDenoter arg1AST, TypeDenoter arg2AST, TypeDenoter resultAST, + SourcePosition position) { + super(position); + O = oAST; + ARG1 = arg1AST; + ARG2 = arg2AST; + RES = resultAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitBinaryOperatorDeclaration(this, arg); + } + + public final Operator O; + public final TypeDenoter ARG1, ARG2, RES; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java new file mode 100644 index 0000000..86bb95a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstDeclaration.java @@ -0,0 +1,42 @@ +/* + * @(#)ConstDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ConstDeclaration extends Declaration implements ConstantDeclaration { + + public ConstDeclaration(Identifier iAST, Expression eAST, SourcePosition position) { + super(position); + I = iAST; + E = eAST; + } + + @Override + public TypeDenoter getType() { + return E.type; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitConstDeclaration(this, arg); + } + + public final Identifier I; + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java new file mode 100644 index 0000000..5241bfc --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ConstantDeclaration.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.types.TypeDenoter; + +public interface ConstantDeclaration { + + TypeDenoter getType(); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java new file mode 100644 index 0000000..ba1b97c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/Declaration.java @@ -0,0 +1,35 @@ +/* + * @(#)Declaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class Declaration extends AbstractSyntaxTree { + + public Declaration(SourcePosition position) { + super(position); + duplicated = false; + } + + public boolean duplicated; + + public abstract TResult visit(DeclarationVisitor visitor, TArg arg); + + public TResult visit(DeclarationVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java new file mode 100644 index 0000000..55272bb --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FuncDeclaration.java @@ -0,0 +1,53 @@ +/* + * @(#)FuncDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class FuncDeclaration extends Declaration implements FunctionDeclaration { + + public FuncDeclaration(Identifier iAST, FormalParameterSequence fpsAST, TypeDenoter tAST, Expression eAST, + SourcePosition position) { + super(position); + I = iAST; + FPS = fpsAST; + T = tAST; + E = eAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitFuncDeclaration(this, arg); + } + + @Override + public FormalParameterSequence getFormals() { + return FPS; + } + + @Override + public TypeDenoter getType() { + return T; + } + + public final Identifier I; + public final FormalParameterSequence FPS; + public TypeDenoter T; + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java new file mode 100644 index 0000000..425fd7c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/FunctionDeclaration.java @@ -0,0 +1,12 @@ +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; +import triangle.abstractSyntaxTrees.types.TypeDenoter; + +public interface FunctionDeclaration { + + FormalParameterSequence getFormals(); + + TypeDenoter getType(); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java new file mode 100644 index 0000000..ba925af --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcDeclaration.java @@ -0,0 +1,44 @@ +/* + * @(#)ProcDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.commands.Command; +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ProcDeclaration extends Declaration implements ProcedureDeclaration { + + public ProcDeclaration(Identifier iAST, FormalParameterSequence fpsAST, Command cAST, SourcePosition position) { + super(position); + I = iAST; + FPS = fpsAST; + C = cAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitProcDeclaration(this, arg); + } + + @Override + public FormalParameterSequence getFormals() { + return FPS; + } + + public final Identifier I; + public final FormalParameterSequence FPS; + public final Command C; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java new file mode 100644 index 0000000..94dee6f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/ProcedureDeclaration.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; + +public interface ProcedureDeclaration { + + FormalParameterSequence getFormals(); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java new file mode 100644 index 0000000..44e6746 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/SequentialDeclaration.java @@ -0,0 +1,33 @@ +/* + * @(#)SequentialDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SequentialDeclaration extends Declaration { + + public SequentialDeclaration(Declaration d1AST, Declaration d2AST, SourcePosition position) { + super(position); + D1 = d1AST; + D2 = d2AST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitSequentialDeclaration(this, arg); + } + + public final Declaration D1, D2; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java new file mode 100644 index 0000000..fd751c6 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/UnaryOperatorDeclaration.java @@ -0,0 +1,37 @@ +/* + * @(#)UnaryOperatorDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class UnaryOperatorDeclaration extends Declaration { + + public UnaryOperatorDeclaration(Operator oAST, TypeDenoter argAST, TypeDenoter resultAST, SourcePosition position) { + super(position); + O = oAST; + ARG = argAST; + RES = resultAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitUnaryOperatorDeclaration(this, arg); + } + + public final Operator O; + public final TypeDenoter ARG, RES; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java new file mode 100644 index 0000000..0933c5f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VarDeclaration.java @@ -0,0 +1,41 @@ +/* + * @(#)VarDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class VarDeclaration extends Declaration implements VariableDeclaration { + + public VarDeclaration(Identifier iAST, TypeDenoter tAST, SourcePosition position) { + super(position); + I = iAST; + T = tAST; + } + + @Override + public TypeDenoter getType() { + return T; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitVarDeclaration(this, arg); + } + + public final Identifier I; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java new file mode 100644 index 0000000..4c4bfd4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/declarations/VariableDeclaration.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.declarations; + +import triangle.abstractSyntaxTrees.types.TypeDenoter; + +public interface VariableDeclaration { + + TypeDenoter getType(); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java new file mode 100644 index 0000000..4fe4325 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/ArrayExpression.java @@ -0,0 +1,33 @@ +/* + * @(#)ArrayExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.aggregates.ArrayAggregate; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ArrayExpression extends Expression { + + public ArrayExpression(ArrayAggregate aaAST, SourcePosition position) { + super(position); + AA = aaAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitArrayExpression(this, arg); + } + + public final ArrayAggregate AA; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java new file mode 100644 index 0000000..f5a992a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/BinaryExpression.java @@ -0,0 +1,37 @@ +/* + * @(#)BinaryExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class BinaryExpression extends Expression { + + public BinaryExpression(Expression e1AST, Operator oAST, Expression e2AST, SourcePosition position) { + super(position); + O = oAST; + E1 = e1AST; + E2 = e2AST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitBinaryExpression(this, arg); + } + + public Expression E1; + public Expression E2; + public final Operator O; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java new file mode 100644 index 0000000..2eeeb66 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CallExpression.java @@ -0,0 +1,36 @@ +/* + * @(#)CallExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class CallExpression extends Expression { + + public CallExpression(Identifier iAST, ActualParameterSequence apsAST, SourcePosition position) { + super(position); + I = iAST; + APS = apsAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitCallExpression(this, arg); + } + + public final Identifier I; + public final ActualParameterSequence APS; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java new file mode 100644 index 0000000..ba2e959 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/CharacterExpression.java @@ -0,0 +1,43 @@ +/* + * @(#)CharacterExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class CharacterExpression extends Expression { + + public CharacterExpression(CharacterLiteral clAST, SourcePosition position) { + super(position); + CL = clAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitCharacterExpression(this, arg); + } + + public final CharacterLiteral CL; + + @Override + public boolean isLiteral() { + return true; + } + + @Override + public int getValue() { + return CL.getValue(); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java new file mode 100644 index 0000000..e1fb097 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/EmptyExpression.java @@ -0,0 +1,29 @@ +/* + * @(#)EmptyExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class EmptyExpression extends Expression { + + public EmptyExpression(SourcePosition position) { + super(position); + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitEmptyExpression(this, arg); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java new file mode 100644 index 0000000..70739bd --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/Expression.java @@ -0,0 +1,44 @@ +/* + * @(#)Expression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class Expression extends AbstractSyntaxTree { + + public Expression(SourcePosition position) { + super(position); + type = null; + } + + public TypeDenoter type; + + public boolean isLiteral() { + return false; + } + + public int getValue() { + throw new UnsupportedOperationException(); + } + + public abstract TResult visit(ExpressionVisitor visitor, TArg arg); + + public TResult visit(ExpressionVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java new file mode 100644 index 0000000..0bd208d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IfExpression.java @@ -0,0 +1,36 @@ +/* + * @(#)IfExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class IfExpression extends Expression { + + public IfExpression(Expression e1AST, Expression e2AST, Expression e3AST, SourcePosition position) { + super(position); + E1 = e1AST; + E2 = e2AST; + E3 = e3AST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitIfExpression(this, arg); + } + + public Expression E1; + public Expression E2; + public Expression E3; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java new file mode 100644 index 0000000..97de244 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/IntegerExpression.java @@ -0,0 +1,43 @@ +/* + * @(#)IntegerExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class IntegerExpression extends Expression { + + public IntegerExpression(IntegerLiteral ilAST, SourcePosition position) { + super(position); + IL = ilAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitIntegerExpression(this, arg); + } + + public final IntegerLiteral IL; + + @Override + public boolean isLiteral() { + return true; + } + + @Override + public int getValue() { + return IL.getValue(); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java new file mode 100644 index 0000000..1bfef81 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/LetExpression.java @@ -0,0 +1,35 @@ +/* + * @(#)LetExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class LetExpression extends Expression { + + public LetExpression(Declaration dAST, Expression eAST, SourcePosition position) { + super(position); + D = dAST; + E = eAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitLetExpression(this, arg); + } + + public final Declaration D; + public Expression E; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java new file mode 100644 index 0000000..ebe59e2 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/RecordExpression.java @@ -0,0 +1,33 @@ +/* + * @(#)RecordExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.aggregates.RecordAggregate; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class RecordExpression extends Expression { + + public RecordExpression(RecordAggregate raAST, SourcePosition position) { + super(position); + RA = raAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitRecordExpression(this, arg); + } + + public final RecordAggregate RA; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java new file mode 100644 index 0000000..22199b9 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/UnaryExpression.java @@ -0,0 +1,35 @@ +/* + * @(#)UnaryExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class UnaryExpression extends Expression { + + public UnaryExpression(Operator oAST, Expression eAST, SourcePosition position) { + super(position); + O = oAST; + E = eAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitUnaryExpression(this, arg); + } + + public Expression E; + public final Operator O; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java new file mode 100644 index 0000000..3bf845a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/expressions/VnameExpression.java @@ -0,0 +1,33 @@ +/* + * @(#)VnameExpression.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.expressions; + +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.syntacticAnalyzer.SourcePosition; + +public class VnameExpression extends Expression { + + public VnameExpression(Vname vAST, SourcePosition position) { + super(position); + V = vAST; + } + + public TResult visit(ExpressionVisitor v, TArg arg) { + return v.visitVnameExpression(this, arg); + } + + public final Vname V; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java new file mode 100644 index 0000000..c860a53 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ConstFormalParameter.java @@ -0,0 +1,51 @@ +/* + * @(#)ConstFormalParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.declarations.ConstantDeclaration; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ConstFormalParameter extends FormalParameter implements ConstantDeclaration { + + public ConstFormalParameter(Identifier iAST, TypeDenoter tAST, SourcePosition position) { + super(position); + I = iAST; + T = tAST; + } + + @Override + public TypeDenoter getType() { + return T; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitConstFormalParameter(this, arg); + } + + @Override + public boolean equals(Object fpAST) { + if (fpAST instanceof ConstFormalParameter) { + return T.equals(((ConstFormalParameter)fpAST).T); + } else { + return false; + } + } + + public final Identifier I; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java new file mode 100644 index 0000000..c478e7f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/EmptyFormalParameterSequence.java @@ -0,0 +1,34 @@ +/* + * @(#)EmptyFormalParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class EmptyFormalParameterSequence extends FormalParameterSequence { + + public EmptyFormalParameterSequence(SourcePosition position) { + super(position); + } + + public TResult visit(FormalParameterSequenceVisitor v, TArg arg) { + return v.visitEmptyFormalParameterSequence(this, arg); + } + + @Override + public boolean equals(Object fpsAST) { + return (fpsAST instanceof EmptyFormalParameterSequence); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java new file mode 100644 index 0000000..b6b643b --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameter.java @@ -0,0 +1,35 @@ +/* + * @(#)FormalParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class FormalParameter extends Declaration { + + public FormalParameter(SourcePosition position) { + super(position); + } + + @Override + public abstract boolean equals(Object fpAST); + + public abstract TResult visit(DeclarationVisitor visitor, TArg arg); + + public TResult visit(DeclarationVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java new file mode 100644 index 0000000..c9941d9 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FormalParameterSequence.java @@ -0,0 +1,35 @@ +/* + * @(#)FormalParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class FormalParameterSequence extends AbstractSyntaxTree { + + public FormalParameterSequence(SourcePosition position) { + super(position); + } + + @Override + public abstract boolean equals(Object fpsAST); + + public abstract TResult visit(FormalParameterSequenceVisitor visitor, TArg arg); + + public TResult visit(FormalParameterSequenceVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java new file mode 100644 index 0000000..f362f25 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/FuncFormalParameter.java @@ -0,0 +1,59 @@ +/* + * @(#)FuncFormalParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.declarations.FunctionDeclaration; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class FuncFormalParameter extends FormalParameter implements FunctionDeclaration { + + public FuncFormalParameter(Identifier iAST, FormalParameterSequence fpsAST, TypeDenoter tAST, + SourcePosition position) { + super(position); + I = iAST; + FPS = fpsAST; + T = tAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitFuncFormalParameter(this, arg); + } + + @Override + public FormalParameterSequence getFormals() { + return FPS; + } + + @Override + public TypeDenoter getType() { + return T; + } + + @Override + public boolean equals(Object fpAST) { + if (fpAST instanceof FuncFormalParameter) { + FuncFormalParameter ffpAST = (FuncFormalParameter) fpAST; + return FPS.equals(ffpAST.FPS) && T.equals(ffpAST.T); + } else + return false; + } + + public final Identifier I; + public final FormalParameterSequence FPS; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java new file mode 100644 index 0000000..32b76fa --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/MultipleFormalParameterSequence.java @@ -0,0 +1,45 @@ +/* + * @(#)MultipleFormalParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class MultipleFormalParameterSequence extends FormalParameterSequence { + + public MultipleFormalParameterSequence(FormalParameter fpAST, FormalParameterSequence fpsAST, + SourcePosition position) { + super(position); + FP = fpAST; + FPS = fpsAST; + } + + public TResult visit(FormalParameterSequenceVisitor v, TArg arg) { + return v.visitMultipleFormalParameterSequence(this, arg); + } + + @Override + public boolean equals(Object fpsAST) { + if (fpsAST instanceof MultipleFormalParameterSequence) { + MultipleFormalParameterSequence mfpsAST = (MultipleFormalParameterSequence) fpsAST; + return FP.equals(mfpsAST.FP) && FPS.equals(mfpsAST.FPS); + } else { + return false; + } + } + + public final FormalParameter FP; + public final FormalParameterSequence FPS; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java new file mode 100644 index 0000000..e89561c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/ProcFormalParameter.java @@ -0,0 +1,51 @@ +/* + * @(#)ProcFormalParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.declarations.ProcedureDeclaration; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ProcFormalParameter extends FormalParameter implements ProcedureDeclaration { + + public ProcFormalParameter(Identifier iAST, FormalParameterSequence fpsAST, SourcePosition position) { + super(position); + I = iAST; + FPS = fpsAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitProcFormalParameter(this, arg); + } + + @Override + public FormalParameterSequence getFormals() { + return FPS; + } + + @Override + public boolean equals(Object fpAST) { + if (fpAST instanceof ProcFormalParameter) { + ProcFormalParameter pfpAST = (ProcFormalParameter) fpAST; + return FPS.equals(pfpAST.FPS); + } else { + return false; + } + } + + public final Identifier I; + public final FormalParameterSequence FPS; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java new file mode 100644 index 0000000..d0f1152 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/SingleFormalParameterSequence.java @@ -0,0 +1,42 @@ +/* + * @(#)SingleFormalParameterSequence.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SingleFormalParameterSequence extends FormalParameterSequence { + + public SingleFormalParameterSequence(FormalParameter fpAST, SourcePosition position) { + super(position); + FP = fpAST; + } + + public TResult visit(FormalParameterSequenceVisitor v, TArg arg) { + return v.visitSingleFormalParameterSequence(this, arg); + } + + @Override + public boolean equals(Object fpsAST) { + if (fpsAST instanceof SingleFormalParameterSequence) { + SingleFormalParameterSequence sfpsAST = (SingleFormalParameterSequence) fpsAST; + return FP.equals(sfpsAST.FP); + } else { + return false; + } + } + + public final FormalParameter FP; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java new file mode 100644 index 0000000..19efd56 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/formals/VarFormalParameter.java @@ -0,0 +1,51 @@ +/* + * @(#)ValFormalParameter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.formals; + +import triangle.abstractSyntaxTrees.declarations.VariableDeclaration; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class VarFormalParameter extends FormalParameter implements VariableDeclaration { + + public VarFormalParameter(Identifier iAST, TypeDenoter tAST, SourcePosition position) { + super(position); + I = iAST; + T = tAST; + } + + @Override + public TypeDenoter getType() { + return T; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitVarFormalParameter(this, arg); + } + + @Override + public boolean equals(Object fpAST) { + if (fpAST instanceof VarFormalParameter) { + return T.equals(((VarFormalParameter)fpAST).T); + } else { + return false; + } + } + + public final Identifier I; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java new file mode 100644 index 0000000..994b8e9 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/CharacterLiteral.java @@ -0,0 +1,37 @@ +/* + * @(#)CharacterLiteral.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.terminals; + +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class CharacterLiteral extends Terminal { + + public CharacterLiteral(String spelling, SourcePosition position) { + super(spelling, position); + } + + public TResult visit(LiteralVisitor v, TArg arg) { + return v.visitCharacterLiteral(this, arg); + } + + public TResult visit(LiteralVisitor visitor) { + return visit(visitor, null); + } + + public int getValue() { + return spelling.charAt(1); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java new file mode 100644 index 0000000..139b2c6 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Identifier.java @@ -0,0 +1,40 @@ +/* + * @(#)Identifier.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.terminals; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class Identifier extends Terminal { + + public Identifier(String spelling, SourcePosition position) { + super(spelling, position); + type = null; + decl = null; + } + + public TypeDenoter type; + public AbstractSyntaxTree decl; // Either a Declaration or a FieldTypeDenoter + + public TResult visit(IdentifierVisitor visitor, TArg arg) { + return visitor.visitIdentifier(this, arg); + } + + public TResult visit(IdentifierVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java new file mode 100644 index 0000000..03be9dc --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/IntegerLiteral.java @@ -0,0 +1,37 @@ +/* + * @(#)IntegerLiteral.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.terminals; + +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class IntegerLiteral extends Terminal { + + public IntegerLiteral(String spelling, SourcePosition position) { + super(spelling, position); + } + + public TResult visit(LiteralVisitor v, TArg arg) { + return v.visitIntegerLiteral(this, arg); + } + + public TResult visit(LiteralVisitor visitor) { + return visit(visitor, null); + } + + public int getValue() { + return Integer.parseInt(spelling); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java new file mode 100644 index 0000000..f6353d1 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Operator.java @@ -0,0 +1,37 @@ +/* + * @(#)Operator.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.terminals; + +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class Operator extends Terminal { + + public Operator(String spelling, SourcePosition position) { + super(spelling, position); + decl = null; + } + + public Declaration decl; + + public TResult visit(OperatorVisitor v, TArg arg) { + return v.visitOperator(this, arg); + } + + public TResult visit(OperatorVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java new file mode 100644 index 0000000..c74ca4b --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/terminals/Terminal.java @@ -0,0 +1,28 @@ +/* + * @(#)Terminal.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.terminals; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class Terminal extends AbstractSyntaxTree { + + public Terminal(String spelling, SourcePosition position) { + super(position); + this.spelling = spelling; + } + + public final String spelling; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java new file mode 100644 index 0000000..171c9ca --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/AnyTypeDenoter.java @@ -0,0 +1,39 @@ +/* + * @(#)AnyTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class AnyTypeDenoter extends TypeDenoter { + + public AnyTypeDenoter(SourcePosition position) { + super(position); + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitAnyTypeDenoter(this, arg); + } + + @Override + public boolean equals(Object obj) { + return false; + } + + @Override + public int getSize() { + return 0; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java new file mode 100644 index 0000000..8d43342 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ArrayTypeDenoter.java @@ -0,0 +1,52 @@ +/* + * @(#)ArrayTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ArrayTypeDenoter extends TypeDenoter { + + public ArrayTypeDenoter(IntegerLiteral ilAST, TypeDenoter tAST, SourcePosition position) { + super(position); + IL = ilAST; + T = tAST; + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitArrayTypeDenoter(this, arg); + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof ErrorTypeDenoter) { + return true; + } else if (obj != null && obj instanceof ArrayTypeDenoter) { + return this.IL.spelling.compareTo(((ArrayTypeDenoter) obj).IL.spelling) == 0 + && this.T.equals(((ArrayTypeDenoter) obj).T); + } else { + return false; + } + } + + @Override + public int getSize() { + return IL.getValue() * T.getSize(); + } + + public final IntegerLiteral IL; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java new file mode 100644 index 0000000..f00e05e --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/BoolTypeDenoter.java @@ -0,0 +1,44 @@ +/* + * @(#)BoolTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractMachine.Machine; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class BoolTypeDenoter extends TypeDenoter { + + public BoolTypeDenoter(SourcePosition position) { + super(position); + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitBoolTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return Machine.booleanSize; + } + + @Override + public boolean equals(Object obj) { + if ((obj != null) && (obj instanceof ErrorTypeDenoter)) { + return true; + } else { + return ((obj != null) && (obj instanceof BoolTypeDenoter)); + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java new file mode 100644 index 0000000..7f474b4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/CharTypeDenoter.java @@ -0,0 +1,44 @@ +/* + * @(#)CharTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractMachine.Machine; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class CharTypeDenoter extends TypeDenoter { + + public CharTypeDenoter(SourcePosition position) { + super(position); + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitCharTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return Machine.characterSize; + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof ErrorTypeDenoter) { + return true; + } else { + return (obj != null && obj instanceof CharTypeDenoter); + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java new file mode 100644 index 0000000..de6ec0a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/ErrorTypeDenoter.java @@ -0,0 +1,39 @@ +/* + * @(#)ErrorTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class ErrorTypeDenoter extends TypeDenoter { + + public ErrorTypeDenoter(SourcePosition position) { + super(position); + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitErrorTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return 0; + } + + @Override + public boolean equals(Object obj) { + return true; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java new file mode 100644 index 0000000..00a2d71 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/FieldTypeDenoter.java @@ -0,0 +1,24 @@ +/* + * @(#)FieldTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class FieldTypeDenoter extends TypeDenoter { + + public FieldTypeDenoter(SourcePosition position) { + super(position); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java new file mode 100644 index 0000000..9c5fb7f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/IntTypeDenoter.java @@ -0,0 +1,44 @@ +/* + * @(#)IntTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractMachine.Machine; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class IntTypeDenoter extends TypeDenoter { + + public IntTypeDenoter(SourcePosition position) { + super(position); + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitIntTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return Machine.integerSize; + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof ErrorTypeDenoter) { + return true; + } else { + return (obj != null && obj instanceof IntTypeDenoter); + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java new file mode 100644 index 0000000..c9b7658 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/MultipleFieldTypeDenoter.java @@ -0,0 +1,53 @@ +/* + * @(#)MultipleFieldTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class MultipleFieldTypeDenoter extends FieldTypeDenoter { + + public MultipleFieldTypeDenoter(Identifier iAST, TypeDenoter tAST, FieldTypeDenoter ftAST, + SourcePosition position) { + super(position); + I = iAST; + T = tAST; + FT = ftAST; + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitMultipleFieldTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return T.getSize() + FT.getSize(); + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof MultipleFieldTypeDenoter) { + MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter) obj; + return (this.I.spelling.compareTo(ft.I.spelling) == 0) && this.T.equals(ft.T) && this.FT.equals(ft.FT); + } else { + return false; + } + } + + public final Identifier I; + public TypeDenoter T; + public FieldTypeDenoter FT; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java new file mode 100644 index 0000000..8ba90d6 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/RecordTypeDenoter.java @@ -0,0 +1,48 @@ +/* + * @(#)RecordTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class RecordTypeDenoter extends TypeDenoter { + + public RecordTypeDenoter(FieldTypeDenoter ftAST, SourcePosition position) { + super(position); + FT = ftAST; + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitRecordTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return FT.getSize(); + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof ErrorTypeDenoter) { + return true; + } else if (obj != null && obj instanceof RecordTypeDenoter) { + return this.FT.equals(((RecordTypeDenoter) obj).FT); + } else { + return false; + } + } + + public FieldTypeDenoter FT; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java new file mode 100644 index 0000000..9d2d2b5 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SimpleTypeDenoter.java @@ -0,0 +1,43 @@ +/* + * @(#)SimpleTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SimpleTypeDenoter extends TypeDenoter { + + public SimpleTypeDenoter(Identifier iAST, SourcePosition position) { + super(position); + I = iAST; + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitSimpleTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return 0; + } + + @Override + public boolean equals(Object obj) { + return false; // should not happen + } + + public final Identifier I; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java new file mode 100644 index 0000000..1471bb0 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/SingleFieldTypeDenoter.java @@ -0,0 +1,50 @@ +/* + * @(#)SingleFieldTypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SingleFieldTypeDenoter extends FieldTypeDenoter { + + public SingleFieldTypeDenoter(Identifier iAST, TypeDenoter tAST, SourcePosition position) { + super(position); + I = iAST; + T = tAST; + } + + public TResult visit(TypeDenoterVisitor v, TArg arg) { + return v.visitSingleFieldTypeDenoter(this, arg); + } + + @Override + public int getSize() { + return T.getSize(); + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof SingleFieldTypeDenoter) { + SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter) obj; + return (this.I.spelling.compareTo(ft.I.spelling) == 0) && this.T.equals(ft.T); + } else { + return false; + } + } + + public final Identifier I; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java new file mode 100644 index 0000000..55e2782 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDeclaration.java @@ -0,0 +1,36 @@ +/* + * @(#)TypeDeclaration.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class TypeDeclaration extends Declaration { + + public TypeDeclaration(Identifier iAST, TypeDenoter tAST, SourcePosition position) { + super(position); + I = iAST; + T = tAST; + } + + public TResult visit(DeclarationVisitor v, TArg arg) { + return v.visitTypeDeclaration(this, arg); + } + + public final Identifier I; + public TypeDenoter T; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java new file mode 100644 index 0000000..b59be4f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/types/TypeDenoter.java @@ -0,0 +1,37 @@ +/* + * @(#)TypeDenoter.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.types; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class TypeDenoter extends AbstractSyntaxTree { + + public TypeDenoter(SourcePosition position) { + super(position); + } + + @Override + public abstract boolean equals(Object obj); + + public abstract TResult visit(TypeDenoterVisitor visitor, TArg arg); + + public TResult visit(TypeDenoterVisitor visitor) { + return visit(visitor, null); + } + + public abstract int getSize(); +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java new file mode 100644 index 0000000..66e68a3 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterSequenceVisitor.java @@ -0,0 +1,15 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; + +public interface ActualParameterSequenceVisitor { + + TResult visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, TArg arg); + + TResult visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, TArg arg); + + TResult visitSingleActualParameterSequence(SingleActualParameterSequence ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java new file mode 100644 index 0000000..9e9630b --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ActualParameterVisitor.java @@ -0,0 +1,18 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; + +public interface ActualParameterVisitor { + + TResult visitConstActualParameter(ConstActualParameter ast, TArg arg); + + TResult visitFuncActualParameter(FuncActualParameter ast, TArg arg); + + TResult visitProcActualParameter(ProcActualParameter ast, TArg arg); + + TResult visitVarActualParameter(VarActualParameter ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java new file mode 100644 index 0000000..8d7abec --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ArrayAggregateVisitor.java @@ -0,0 +1,12 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; + +public interface ArrayAggregateVisitor { + + TResult visitMultipleArrayAggregate(MultipleArrayAggregate ast, TArg arg); + + TResult visitSingleArrayAggregate(SingleArrayAggregate ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java new file mode 100644 index 0000000..336c97d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/CommandVisitor.java @@ -0,0 +1,27 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; + +public interface CommandVisitor { + + TResult visitAssignCommand(AssignCommand ast, TArg arg); + + TResult visitCallCommand(CallCommand ast, TArg arg); + + TResult visitEmptyCommand(EmptyCommand ast, TArg arg); + + TResult visitIfCommand(IfCommand ast, TArg arg); + + TResult visitLetCommand(LetCommand ast, TArg arg); + + TResult visitSequentialCommand(SequentialCommand ast, TArg arg); + + TResult visitWhileCommand(WhileCommand ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java new file mode 100644 index 0000000..7ce845d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/DeclarationVisitor.java @@ -0,0 +1,30 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; + +public interface DeclarationVisitor extends FormalParameterVisitor { + + TResult visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, TArg arg); + + TResult visitConstDeclaration(ConstDeclaration ast, TArg arg); + + TResult visitFuncDeclaration(FuncDeclaration ast, TArg arg); + + TResult visitProcDeclaration(ProcDeclaration ast, TArg arg); + + TResult visitSequentialDeclaration(SequentialDeclaration ast, TArg arg); + + TResult visitTypeDeclaration(TypeDeclaration ast, TArg arg); + + TResult visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, TArg arg); + + TResult visitVarDeclaration(VarDeclaration ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java new file mode 100644 index 0000000..ebb76f4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ExpressionVisitor.java @@ -0,0 +1,39 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.EmptyExpression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; + +public interface ExpressionVisitor { + + TResult visitArrayExpression(ArrayExpression ast, TArg arg); + + TResult visitBinaryExpression(BinaryExpression ast, TArg arg); + + TResult visitCallExpression(CallExpression ast, TArg arg); + + TResult visitCharacterExpression(CharacterExpression ast, TArg arg); + + TResult visitEmptyExpression(EmptyExpression ast, TArg arg); + + TResult visitIfExpression(IfExpression ast, TArg arg); + + TResult visitIntegerExpression(IntegerExpression ast, TArg arg); + + TResult visitLetExpression(LetExpression ast, TArg arg); + + TResult visitRecordExpression(RecordExpression ast, TArg arg); + + TResult visitUnaryExpression(UnaryExpression ast, TArg arg); + + TResult visitVnameExpression(VnameExpression ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java new file mode 100644 index 0000000..2bd3f0d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FieldTypeDenoterVisitor.java @@ -0,0 +1,12 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; + +public interface FieldTypeDenoterVisitor { + + TResult visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, TArg arg); + + TResult visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java new file mode 100644 index 0000000..3505451 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterSequenceVisitor.java @@ -0,0 +1,15 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; + +public interface FormalParameterSequenceVisitor { + + TResult visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, TArg arg); + + TResult visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, TArg arg); + + TResult visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java new file mode 100644 index 0000000..cddb0e7 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/FormalParameterVisitor.java @@ -0,0 +1,18 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; + +public interface FormalParameterVisitor { + + TResult visitConstFormalParameter(ConstFormalParameter ast, TArg arg); + + TResult visitFuncFormalParameter(FuncFormalParameter ast, TArg arg); + + TResult visitProcFormalParameter(ProcFormalParameter ast, TArg arg); + + TResult visitVarFormalParameter(VarFormalParameter ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java new file mode 100644 index 0000000..b303b8e --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/IdentifierVisitor.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.terminals.Identifier; + +public interface IdentifierVisitor { + + TResult visitIdentifier(Identifier ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java new file mode 100644 index 0000000..1ca4fa4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/LiteralVisitor.java @@ -0,0 +1,12 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; + +public interface LiteralVisitor { + + TResult visitCharacterLiteral(CharacterLiteral ast, TArg arg); + + TResult visitIntegerLiteral(IntegerLiteral ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java new file mode 100644 index 0000000..989a653 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/OperatorVisitor.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.terminals.Operator; + +public interface OperatorVisitor { + + TResult visitOperator(Operator ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java new file mode 100644 index 0000000..aca855c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/ProgramVisitor.java @@ -0,0 +1,9 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.Program; + +public interface ProgramVisitor { + + TResult visitProgram(Program ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java new file mode 100644 index 0000000..20ed097 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/RecordAggregateVisitor.java @@ -0,0 +1,12 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; + +public interface RecordAggregateVisitor { + + TResult visitMultipleRecordAggregate(MultipleRecordAggregate ast, TArg arg); + + TResult visitSingleRecordAggregate(SingleRecordAggregate ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java new file mode 100644 index 0000000..79b47e3 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/TypeDenoterVisitor.java @@ -0,0 +1,30 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; +import triangle.abstractSyntaxTrees.types.CharTypeDenoter; +import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; +import triangle.abstractSyntaxTrees.types.IntTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; + +public interface TypeDenoterVisitor extends FieldTypeDenoterVisitor { + + TResult visitAnyTypeDenoter(AnyTypeDenoter ast, TArg arg); + + TResult visitArrayTypeDenoter(ArrayTypeDenoter ast, TArg arg); + + TResult visitBoolTypeDenoter(BoolTypeDenoter ast, TArg arg); + + TResult visitCharTypeDenoter(CharTypeDenoter ast, TArg arg); + + TResult visitErrorTypeDenoter(ErrorTypeDenoter ast, TArg arg); + + TResult visitSimpleTypeDenoter(SimpleTypeDenoter ast, TArg arg); + + TResult visitIntTypeDenoter(IntTypeDenoter ast, TArg arg); + + TResult visitRecordTypeDenoter(RecordTypeDenoter ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java new file mode 100644 index 0000000..6936a54 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/visitors/VnameVisitor.java @@ -0,0 +1,15 @@ +package triangle.abstractSyntaxTrees.visitors; + +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; + +public interface VnameVisitor { + + TResult visitDotVname(DotVname ast, TArg arg); + + TResult visitSimpleVname(SimpleVname ast, TArg arg); + + TResult visitSubscriptVname(SubscriptVname ast, TArg arg); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java new file mode 100644 index 0000000..81c1d41 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/DotVname.java @@ -0,0 +1,35 @@ +/* + * @(#)DotVname.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.vnames; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class DotVname extends Vname { + + public DotVname(Vname vAST, Identifier iAST, SourcePosition position) { + super(position); + V = vAST; + I = iAST; + } + + public TResult visit(VnameVisitor v, TArg arg) { + return v.visitDotVname(this, arg); + } + + public final Identifier I; + public final Vname V; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java new file mode 100644 index 0000000..c1ca042 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SimpleVname.java @@ -0,0 +1,33 @@ +/* + * @(#)SimpleVname.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.vnames; + +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SimpleVname extends Vname { + + public SimpleVname(Identifier iAST, SourcePosition position) { + super(position); + I = iAST; + } + + public TResult visit(VnameVisitor v, TArg arg) { + return v.visitSimpleVname(this, arg); + } + + public final Identifier I; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java new file mode 100644 index 0000000..a95d1f4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/SubscriptVname.java @@ -0,0 +1,35 @@ +/* + * @(#)SubscriptVname.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.vnames; + +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public class SubscriptVname extends Vname { + + public SubscriptVname(Vname vAST, Expression eAST, SourcePosition position) { + super(position); + V = vAST; + E = eAST; + } + + public TResult visit(VnameVisitor v, TArg arg) { + return v.visitSubscriptVname(this, arg); + } + + public Expression E; + public final Vname V; +} diff --git a/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java new file mode 100644 index 0000000..633b1f0 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/abstractSyntaxTrees/vnames/Vname.java @@ -0,0 +1,39 @@ +/* + * @(#)Vname.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.abstractSyntaxTrees.vnames; + +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.syntacticAnalyzer.SourcePosition; + +public abstract class Vname extends AbstractSyntaxTree { + + public Vname(SourcePosition position) { + super(position); + variable = false; + type = null; + } + + public boolean variable, indexed; + public int offset; + public TypeDenoter type; + + public abstract TResult visit(VnameVisitor visitor, TArg arg); + + public TResult visit(VnameVisitor visitor) { + return visit(visitor, null); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java new file mode 100644 index 0000000..e0b037a --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Emitter.java @@ -0,0 +1,120 @@ +package triangle.codeGenerator; + +import java.io.DataOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import triangle.ErrorReporter; +import triangle.abstractMachine.Instruction; +import triangle.abstractMachine.Machine; +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; + +public class Emitter { + + // OBJECT CODE + + // Implementation notes: + // Object code is generated directly into the TAM Code Store, starting at + // CB. + // The address of the next instruction is held in nextInstrAddr. + + ErrorReporter errorReporter; + + int nextInstrAddr; + + public Emitter(ErrorReporter errorReporter) { + this.errorReporter = errorReporter; + nextInstrAddr = Machine.CB; + } + + public int getNextInstrAddr() { + return nextInstrAddr; + } + + public int emit(OpCode op) { + return emit(op, 0, Register.CB, 0); + } + + public int emit(OpCode op, int operand) { + return emit(op, 0, Register.CB, operand); + } + + public int emit(OpCode op, int length, int operand) { + return emit(op, length, Register.CB, operand); + } + + public int emit(OpCode op, Register staticRegister, Register register, int operand) { + return emit(op, staticRegister.ordinal(), register, operand); + } + + public int emit(OpCode op, Register register, int operand) { + return emit(op, 0, register, operand); + } + + public int emit(OpCode op, Register register) { + return emit(op, 0, register, 0); + } + + public int emit(OpCode op, int length, Register register) { + return emit(op, length, register, 0); + } + + public int emit(OpCode op, Register register, Primitive primitive) { + return emit(op, 0, register, primitive.ordinal()); + } + + /** + * Appends an instruction, with the given fields, to the object code. + * + * @param op the opcode + * @param length the length field + * @param register the register field + * @param operand the operand field + * @return the code address of the new instruction + **/ + public int emit(OpCode op, int length, Register register, int operand) { + + if (length > 255) { + errorReporter.reportRestriction("length of operand can't exceed 255 words"); + length = 255; // to allow code generation to continue + } + + var nextInstr = new Instruction(op, register, length, operand); + + var currentInstrAddr = nextInstrAddr; + if (nextInstrAddr == Machine.PB) { + errorReporter.reportRestriction("too many instructions for code segment"); + } else { + Machine.code[nextInstrAddr++] = nextInstr; + } + return currentInstrAddr; + + } + + // Patches the d-field of the instruction at address addr with the next + // instruction address. + public void patch(int addr) { + Machine.code[addr].setOperand(nextInstrAddr); + } + + /** + * Saves the object program in the given object file. + * + * @param objectFile the object file + */ + public void saveObjectProgram(String objectFileName) { + try (var objectFile = new FileOutputStream(objectFileName)) { + var objectStream = new DataOutputStream(objectFile); + for (var addr = Machine.CB; addr < nextInstrAddr; addr++) { + Machine.code[addr].write(objectStream); + } + } catch (FileNotFoundException fnfe) { + System.err.println("Error opening object file: " + fnfe); + } catch (IOException ioe) { + System.err.println("Error writing object file: " + ioe); + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java new file mode 100644 index 0000000..2224aa6 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Encoder.java @@ -0,0 +1,792 @@ +/* + * @(#)Encoder.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator; + +import triangle.ErrorReporter; +import triangle.StdEnvironment; +import triangle.abstractMachine.Machine; +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.Program; +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.EmptyExpression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; +import triangle.abstractSyntaxTrees.types.CharTypeDenoter; +import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; +import triangle.abstractSyntaxTrees.types.IntTypeDenoter; +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; +import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.entities.AddressableEntity; +import triangle.codeGenerator.entities.EqualityRoutine; +import triangle.codeGenerator.entities.FetchableEntity; +import triangle.codeGenerator.entities.Field; +import triangle.codeGenerator.entities.KnownAddress; +import triangle.codeGenerator.entities.KnownRoutine; +import triangle.codeGenerator.entities.KnownValue; +import triangle.codeGenerator.entities.PrimitiveRoutine; +import triangle.codeGenerator.entities.RoutineEntity; +import triangle.codeGenerator.entities.RuntimeEntity; +import triangle.codeGenerator.entities.TypeRepresentation; +import triangle.codeGenerator.entities.UnknownAddress; +import triangle.codeGenerator.entities.UnknownRoutine; +import triangle.codeGenerator.entities.UnknownValue; + +public final class Encoder implements ActualParameterVisitor, + ActualParameterSequenceVisitor, ArrayAggregateVisitor, + CommandVisitor, DeclarationVisitor, ExpressionVisitor, + FormalParameterSequenceVisitor, IdentifierVisitor, LiteralVisitor, + OperatorVisitor, ProgramVisitor, RecordAggregateVisitor, + TypeDenoterVisitor, VnameVisitor { + + // Commands + @Override + public Void visitAssignCommand(AssignCommand ast, Frame frame) { + var valSize = ast.E.visit(this, frame); + encodeStore(ast.V, frame.expand(valSize), valSize); + return null; + } + + @Override + public Void visitCallCommand(CallCommand ast, Frame frame) { + var argsSize = ast.APS.visit(this, frame); + ast.I.visit(this, frame.replace(argsSize)); + return null; + } + + @Override + public Void visitEmptyCommand(EmptyCommand ast, Frame frame) { + return null; + } + + @Override + public Void visitIfCommand(IfCommand ast, Frame frame) { + ast.E.visit(this, frame); + var jumpifAddr = emitter.emit(OpCode.JUMPIF, Machine.falseRep, Register.CB, 0); + ast.C1.visit(this, frame); + var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0); + emitter.patch(jumpifAddr); + ast.C2.visit(this, frame); + emitter.patch(jumpAddr); + return null; + } + + @Override + public Void visitLetCommand(LetCommand ast, Frame frame) { + var extraSize = ast.D.visit(this, frame); + ast.C.visit(this, frame.expand(extraSize)); + if (extraSize > 0) { + emitter.emit(OpCode.POP, extraSize); + } + return null; + } + + @Override + public Void visitSequentialCommand(SequentialCommand ast, Frame frame) { + ast.C1.visit(this, frame); + ast.C2.visit(this, frame); + return null; + } + + @Override + public Void visitWhileCommand(WhileCommand ast, Frame frame) { + var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0); + var loopAddr = emitter.getNextInstrAddr(); + ast.C.visit(this, frame); + emitter.patch(jumpAddr); + ast.E.visit(this, frame); + emitter.emit(OpCode.JUMPIF, Machine.trueRep, Register.CB, loopAddr); + return null; + } + + // Expressions + @Override + public Integer visitArrayExpression(ArrayExpression ast, Frame frame) { + ast.type.visit(this, frame); + return ast.AA.visit(this, frame); + } + + @Override + public Integer visitBinaryExpression(BinaryExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + var valSize1 = ast.E1.visit(this, frame); + var frame1 = frame.expand(valSize1); + var valSize2 = ast.E2.visit(this, frame1); + var frame2 = frame.replace(valSize1 + valSize2); + ast.O.visit(this, frame2); + return valSize; + } + + @Override + public Integer visitCallExpression(CallExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + var argsSize = ast.APS.visit(this, frame); + ast.I.visit(this, frame.replace(argsSize)); + return valSize; + } + + @Override + public Integer visitCharacterExpression(CharacterExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + emitter.emit(OpCode.LOADL, ast.CL.getValue()); + return valSize; + } + + @Override + public Integer visitEmptyExpression(EmptyExpression ast, Frame frame) { + return 0; + } + + @Override + public Integer visitIfExpression(IfExpression ast, Frame frame) { + ast.type.visit(this); + ast.E1.visit(this, frame); + var jumpifAddr = emitter.emit(OpCode.JUMPIF, Machine.falseRep, Register.CB, 0); + var valSize = ast.E2.visit(this, frame); + var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0); + emitter.patch(jumpifAddr); + valSize = ast.E3.visit(this, frame); + emitter.patch(jumpAddr); + return valSize; + } + + @Override + public Integer visitIntegerExpression(IntegerExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + emitter.emit(OpCode.LOADL, ast.IL.getValue()); + return valSize; + } + + @Override + public Integer visitLetExpression(LetExpression ast, Frame frame) { + ast.type.visit(this); + var extraSize = ast.D.visit(this, frame); + var frame1 = frame.expand(extraSize); + var valSize = ast.E.visit(this, frame1); + if (extraSize > 0) { + emitter.emit(OpCode.POP, valSize, extraSize); + } + return valSize; + } + + @Override + public Integer visitRecordExpression(RecordExpression ast, Frame frame) { + ast.type.visit(this); + return ast.RA.visit(this, frame); + } + + @Override + public Integer visitUnaryExpression(UnaryExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + ast.E.visit(this, frame); + ast.O.visit(this, frame.replace(valSize)); + return valSize; + } + + @Override + public Integer visitVnameExpression(VnameExpression ast, Frame frame) { + var valSize = ast.type.visit(this); + encodeFetch(ast.V, frame, valSize); + return valSize; + } + + // Declarations + @Override + public Integer visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Frame frame) { + return 0; + } + + @Override + public Integer visitConstDeclaration(ConstDeclaration ast, Frame frame) { + var extraSize = 0; + if (ast.E.isLiteral()) { + ast.entity = new KnownValue(ast.E.type.getSize(), ast.E.getValue()); + } else { + var valSize = ast.E.visit(this, frame); + ast.entity = new UnknownValue(valSize, frame); + extraSize = valSize; + } + writeTableDetails(ast); + return extraSize; + } + + @Override + public Integer visitFuncDeclaration(FuncDeclaration ast, Frame frame) { + var argsSize = 0; + var valSize = 0; + + var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0); + ast.entity = new KnownRoutine(Machine.closureSize, frame.getLevel(), emitter.getNextInstrAddr()); + writeTableDetails(ast); + if (frame.getLevel() == Machine.maxRoutineLevel) { + reporter.reportRestriction("can't nest routines more than 7 deep"); + } else { + var frame1 = frame.push(0); + argsSize = ast.FPS.visit(this, frame1); + var frame2 = frame.push(Machine.linkDataSize); + valSize = ast.E.visit(this, frame2); + } + emitter.emit(OpCode.RETURN, valSize, argsSize); + emitter.patch(jumpAddr); + return 0; + } + + @Override + public Integer visitProcDeclaration(ProcDeclaration ast, Frame frame) { + var argsSize = 0; + var jumpAddr = emitter.emit(OpCode.JUMP, 0, Register.CB, 0); + ast.entity = new KnownRoutine(Machine.closureSize, frame.getLevel(), emitter.getNextInstrAddr()); + writeTableDetails(ast); + if (frame.getLevel() == Machine.maxRoutineLevel) { + reporter.reportRestriction("can't nest routines so deeply"); + } else { + var frame1 = frame.push(0); + argsSize = ast.FPS.visit(this, frame1); + var frame2 = frame.push(Machine.linkDataSize); + ast.C.visit(this, frame2); + } + emitter.emit(OpCode.RETURN, argsSize); + emitter.patch(jumpAddr); + return 0; + } + + @Override + public Integer visitSequentialDeclaration(SequentialDeclaration ast, Frame frame) { + var extraSize1 = ast.D1.visit(this, frame); + var frame1 = frame.expand(extraSize1); + var extraSize2 = ast.D2.visit(this, frame1); + return extraSize1 + extraSize2; + } + + @Override + public Integer visitTypeDeclaration(TypeDeclaration ast, Frame frame) { + // just to ensure the type's representation is decided + ast.T.visit(this); + return 0; + } + + @Override + public Integer visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Frame frame) { + return 0; + } + + @Override + public Integer visitVarDeclaration(VarDeclaration ast, Frame frame) { + var extraSize = ast.T.visit(this); + emitter.emit(OpCode.PUSH, extraSize); + ast.entity = new KnownAddress(Machine.addressSize, frame); + writeTableDetails(ast); + return extraSize; + } + + // Array Aggregates + @Override + public Integer visitMultipleArrayAggregate(MultipleArrayAggregate ast, Frame frame) { + var elemSize = ast.E.visit(this, frame); + var frame1 = frame.expand(elemSize); + var arraySize = ast.AA.visit(this, frame1); + return elemSize + arraySize; + } + + @Override + public Integer visitSingleArrayAggregate(SingleArrayAggregate ast, Frame frame) { + return ast.E.visit(this, frame); + } + + // Record Aggregates + @Override + public Integer visitMultipleRecordAggregate(MultipleRecordAggregate ast, Frame frame) { + var fieldSize = ast.E.visit(this, frame); + var frame1 = frame.expand(fieldSize); + var recordSize = ast.RA.visit(this, frame1); + return fieldSize + recordSize; + } + + @Override + public Integer visitSingleRecordAggregate(SingleRecordAggregate ast, Frame frame) { + return ast.E.visit(this, frame); + } + + // Formal Parameters + @Override + public Integer visitConstFormalParameter(ConstFormalParameter ast, Frame frame) { + var valSize = ast.T.visit(this); + ast.entity = new UnknownValue(valSize, frame.getLevel(), -frame.getSize() - valSize); + writeTableDetails(ast); + return valSize; + } + + @Override + public Integer visitFuncFormalParameter(FuncFormalParameter ast, Frame frame) { + var argsSize = Machine.closureSize; + ast.entity = new UnknownRoutine(Machine.closureSize, frame.getLevel(), -frame.getSize() - argsSize); + writeTableDetails(ast); + return argsSize; + } + + @Override + public Integer visitProcFormalParameter(ProcFormalParameter ast, Frame frame) { + var argsSize = Machine.closureSize; + ast.entity = new UnknownRoutine(Machine.closureSize, frame.getLevel(), -frame.getSize() - argsSize); + writeTableDetails(ast); + return argsSize; + } + + @Override + public Integer visitVarFormalParameter(VarFormalParameter ast, Frame frame) { + ast.T.visit(this); + ast.entity = new UnknownAddress(Machine.addressSize, frame.getLevel(), -frame.getSize() - Machine.addressSize); + writeTableDetails(ast); + return Machine.addressSize; + } + + @Override + public Integer visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Frame frame) { + return 0; + } + + @Override + public Integer visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Frame frame) { + var argsSize1 = ast.FPS.visit(this, frame); + var frame1 = frame.expand(argsSize1); + var argsSize2 = ast.FP.visit(this, frame1); + return argsSize1 + argsSize2; + } + + @Override + public Integer visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Frame frame) { + return ast.FP.visit(this, frame); + } + + // Actual Parameters + @Override + public Integer visitConstActualParameter(ConstActualParameter ast, Frame frame) { + return ast.E.visit(this, frame); + } + + @Override + public Integer visitFuncActualParameter(FuncActualParameter ast, Frame frame) { + var routineEntity = (RoutineEntity) ast.I.decl.entity; + routineEntity.encodeFetch(emitter, frame); + return Machine.closureSize; + } + + @Override + public Integer visitProcActualParameter(ProcActualParameter ast, Frame frame) { + var routineEntity = (RoutineEntity) ast.I.decl.entity; + routineEntity.encodeFetch(emitter, frame); + return Machine.closureSize; + } + + @Override + public Integer visitVarActualParameter(VarActualParameter ast, Frame frame) { + encodeFetchAddress(ast.V, frame); + return Machine.addressSize; + } + + @Override + public Integer visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Frame frame) { + return 0; + } + + @Override + public Integer visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Frame frame) { + var argsSize1 = ast.AP.visit(this, frame); + var frame1 = frame.expand(argsSize1); + var argsSize2 = ast.APS.visit(this, frame1); + return argsSize1 + argsSize2; + } + + @Override + public Integer visitSingleActualParameterSequence(SingleActualParameterSequence ast, Frame frame) { + return ast.AP.visit(this, frame); + } + + // Type Denoters + @Override + public Integer visitAnyTypeDenoter(AnyTypeDenoter ast, Frame frame) { + return 0; + } + + @Override + public Integer visitArrayTypeDenoter(ArrayTypeDenoter ast, Frame frame) { + int typeSize; + if (ast.entity == null) { + var elemSize = ast.T.visit(this); + typeSize = ast.IL.getValue() * elemSize; + ast.entity = new TypeRepresentation(typeSize); + writeTableDetails(ast); + } else { + typeSize = ast.entity.getSize(); + } + return typeSize; + } + + @Override + public Integer visitBoolTypeDenoter(BoolTypeDenoter ast, Frame frame) { + if (ast.entity == null) { + ast.entity = new TypeRepresentation(Machine.booleanSize); + writeTableDetails(ast); + } + return Machine.booleanSize; + } + + @Override + public Integer visitCharTypeDenoter(CharTypeDenoter ast, Frame frame) { + if (ast.entity == null) { + ast.entity = new TypeRepresentation(Machine.characterSize); + writeTableDetails(ast); + } + return Machine.characterSize; + } + + @Override + public Integer visitErrorTypeDenoter(ErrorTypeDenoter ast, Frame frame) { + return 0; + } + + @Override + public Integer visitSimpleTypeDenoter(SimpleTypeDenoter ast, Frame frame) { + return 0; + } + + @Override + public Integer visitIntTypeDenoter(IntTypeDenoter ast, Frame frame) { + if (ast.entity == null) { + ast.entity = new TypeRepresentation(Machine.integerSize); + writeTableDetails(ast); + } + return Machine.integerSize; + } + + @Override + public Integer visitRecordTypeDenoter(RecordTypeDenoter ast, Frame frame) { + int typeSize; + if (ast.entity == null) { + typeSize = ast.FT.visit(this, frame); + ast.entity = new TypeRepresentation(typeSize); + writeTableDetails(ast); + } else { + typeSize = ast.entity.getSize(); + } + return typeSize; + } + + @Override + public Integer visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Frame frame) { + if (frame == null) { // in this case, we're just using the frame to wrap up the size + frame = Frame.Initial; + } + + var offset = frame.getSize(); + int fieldSize; + if (ast.entity == null) { + fieldSize = ast.T.visit(this); + ast.entity = new Field(fieldSize, offset); + writeTableDetails(ast); + } else { + fieldSize = ast.entity.getSize(); + } + + var offset1 = frame.replace(offset + fieldSize); + var recSize = ast.FT.visit(this, offset1); + return fieldSize + recSize; + } + + @Override + public Integer visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Frame frame) { + var offset = frame.getSize(); + int fieldSize; + if (ast.entity == null) { + fieldSize = ast.T.visit(this); + ast.entity = new Field(fieldSize, offset); + writeTableDetails(ast); + } else { + fieldSize = ast.entity.getSize(); + } + + return fieldSize; + } + + // Literals, Identifiers and Operators + @Override + public Void visitCharacterLiteral(CharacterLiteral ast, Void arg) { + return null; + } + + @Override + public Void visitIdentifier(Identifier ast, Frame frame) { + var routineEntity = (RoutineEntity) ast.decl.entity; + routineEntity.encodeCall(emitter, frame); + return null; + } + + @Override + public Void visitIntegerLiteral(IntegerLiteral ast, Void arg) { + return null; + } + + @Override + public Void visitOperator(Operator ast, Frame frame) { + var routineEntity = (RoutineEntity) ast.decl.entity; + routineEntity.encodeCall(emitter, frame); + return null; + } + + // Value-or-variable names + @Override + public RuntimeEntity visitDotVname(DotVname ast, Frame frame) { + var baseObject = ast.V.visit(this, frame); + ast.offset = ast.V.offset + ((Field) ast.I.decl.entity).getFieldOffset(); + // I.decl points to the appropriate record field + ast.indexed = ast.V.indexed; + return baseObject; + } + + @Override + public RuntimeEntity visitSimpleVname(SimpleVname ast, Frame frame) { + ast.offset = 0; + ast.indexed = false; + return ast.I.decl.entity; + } + + @Override + public RuntimeEntity visitSubscriptVname(SubscriptVname ast, Frame frame) { + var baseObject = ast.V.visit(this, frame); + ast.offset = ast.V.offset; + ast.indexed = ast.V.indexed; + var elemSize = ast.type.visit(this); + if (ast.E.isLiteral()) { + ast.offset = ast.offset + ast.E.getValue() * elemSize; + } else { + // v-name is indexed by a proper expression, not a literal + if (ast.indexed) { + frame = frame.expand(Machine.integerSize); + } + ast.E.visit(this, frame); + if (elemSize != 1) { + emitter.emit(OpCode.LOADL, 0, elemSize); + emitter.emit(OpCode.CALL, Register.PB, Primitive.MULT); + } + if (ast.indexed) + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + else { + ast.indexed = true; + } + } + return baseObject; + } + + // Programs + @Override + public Void visitProgram(Program ast, Frame frame) { + return ast.C.visit(this, frame); + } + + public Encoder(Emitter emitter, ErrorReporter reporter) { + this.emitter = emitter; + this.reporter = reporter; + + elaborateStdEnvironment(); + } + + private Emitter emitter; + + private ErrorReporter reporter; + + // Generates code to run a program. + // showingTable is true iff entity description details + // are to be displayed. + public final void encodeRun(Program program, boolean showingTable) { + tableDetailsReqd = showingTable; + // startCodeGeneration(); + program.visit(this, Frame.Initial); + emitter.emit(OpCode.HALT); + } + + // Decides run-time representation of a standard constant. + private final void elaborateStdConst(ConstDeclaration constDeclaration, int value) { + + var typeSize = constDeclaration.E.type.visit(this); + constDeclaration.entity = new KnownValue(typeSize, value); + writeTableDetails(constDeclaration); + } + + // Decides run-time representation of a standard routine. + private final void elaborateStdPrimRoutine(Declaration routineDeclaration, Primitive primitive) { + routineDeclaration.entity = new PrimitiveRoutine(Machine.closureSize, primitive); + writeTableDetails(routineDeclaration); + } + + private final void elaborateStdEqRoutine(Declaration routineDeclaration, Primitive primitive) { + routineDeclaration.entity = new EqualityRoutine(Machine.closureSize, primitive); + writeTableDetails(routineDeclaration); + } + + private final void elaborateStdEnvironment() { + tableDetailsReqd = false; + elaborateStdConst(StdEnvironment.falseDecl, Machine.falseRep); + elaborateStdConst(StdEnvironment.trueDecl, Machine.trueRep); + elaborateStdPrimRoutine(StdEnvironment.notDecl, Primitive.NOT); + elaborateStdPrimRoutine(StdEnvironment.andDecl, Primitive.AND); + elaborateStdPrimRoutine(StdEnvironment.orDecl, Primitive.OR); + elaborateStdConst(StdEnvironment.maxintDecl, Machine.maxintRep); + elaborateStdPrimRoutine(StdEnvironment.addDecl, Primitive.ADD); + elaborateStdPrimRoutine(StdEnvironment.subtractDecl, Primitive.SUB); + elaborateStdPrimRoutine(StdEnvironment.multiplyDecl, Primitive.MULT); + elaborateStdPrimRoutine(StdEnvironment.divideDecl, Primitive.DIV); + elaborateStdPrimRoutine(StdEnvironment.moduloDecl, Primitive.MOD); + elaborateStdPrimRoutine(StdEnvironment.lessDecl, Primitive.LT); + elaborateStdPrimRoutine(StdEnvironment.notgreaterDecl, Primitive.LE); + elaborateStdPrimRoutine(StdEnvironment.greaterDecl, Primitive.GT); + elaborateStdPrimRoutine(StdEnvironment.notlessDecl, Primitive.GE); + elaborateStdPrimRoutine(StdEnvironment.chrDecl, Primitive.ID); + elaborateStdPrimRoutine(StdEnvironment.ordDecl, Primitive.ID); + elaborateStdPrimRoutine(StdEnvironment.eolDecl, Primitive.EOL); + elaborateStdPrimRoutine(StdEnvironment.eofDecl, Primitive.EOF); + elaborateStdPrimRoutine(StdEnvironment.getDecl, Primitive.GET); + elaborateStdPrimRoutine(StdEnvironment.putDecl, Primitive.PUT); + elaborateStdPrimRoutine(StdEnvironment.getintDecl, Primitive.GETINT); + elaborateStdPrimRoutine(StdEnvironment.putintDecl, Primitive.PUTINT); + elaborateStdPrimRoutine(StdEnvironment.geteolDecl, Primitive.GETEOL); + elaborateStdPrimRoutine(StdEnvironment.puteolDecl, Primitive.PUTEOL); + elaborateStdEqRoutine(StdEnvironment.equalDecl, Primitive.EQ); + elaborateStdEqRoutine(StdEnvironment.unequalDecl, Primitive.NE); + } + + boolean tableDetailsReqd; + + public static void writeTableDetails(AbstractSyntaxTree ast) { + } + + // Generates code to pop the top off the stack + // and store the value in a named constant or variable + // frame the local stack frame when + // the constant or variable is fetched at run-time. + // valSize is the size of the constant or variable's value. + + private void encodeStore(Vname V, Frame frame, int valSize) { + + var baseObject = (AddressableEntity) V.visit(this, frame); + // If indexed = true, code will have been generated to load an index value. + if (valSize > 255) { + reporter.reportRestriction("can't store values larger than 255 words"); + valSize = 255; // to allow code generation to continue + } + + baseObject.encodeStore(emitter, frame, valSize, V); + } + + // Generates code to fetch the value of a named constant or variable + // and push it on to the stack. + // currentLevel is the routine level where the vname occurs. + // frameSize is the anticipated size of the local stack frame when + // the constant or variable is fetched at run-time. + // valSize is the size of the constant or variable's value. + + private void encodeFetch(Vname V, Frame frame, int valSize) { + + var baseObject = (FetchableEntity) V.visit(this, frame); + // If indexed = true, code will have been generated to load an index value. + if (valSize > 255) { + reporter.reportRestriction("can't load values larger than 255 words"); + valSize = 255; // to allow code generation to continue + } + + baseObject.encodeFetch(emitter, frame, valSize, V); + } + + // Generates code to compute and push the address of a named variable. + // vname is the program phrase that names this variable. + // currentLevel is the routine level where the vname occurs. + // frameSize is the anticipated size of the local stack frame when + // the variable is addressed at run-time. + + private void encodeFetchAddress(Vname V, Frame frame) { + + var baseObject = (AddressableEntity) V.visit(this, frame); + baseObject.encodeFetchAddress(emitter, frame, V); + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java new file mode 100644 index 0000000..5aba4e4 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/Frame.java @@ -0,0 +1,73 @@ +/* + * @(#)Frame.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator; + +import triangle.abstractMachine.Register; +import triangle.codeGenerator.entities.ObjectAddress; + +public class Frame { + + public static final Frame Initial = new Frame(0, 0); + + private final int level; + + private final int size; + + private Frame(int level, int size) { + this.level = level; + this.size = size; + } + + public final int getLevel() { + return level; + } + + public final int getSize() { + return size; + } + + public Frame expand(int increment) { + return new Frame(level, size + increment); + } + + public Frame replace(int size) { + return new Frame(level, size); + } + + public Frame push(int size) { + return new Frame(level + 1, size); + } + + /** + * Returns the display register appropriate for object code at the current + * static level to access a data object at the static level of the given + * address. + * + * @param address the address of the data object + * @return the display register required for static addressing + */ + public Register getDisplayRegister(ObjectAddress address) { + if (address.getLevel() == 0) { + return Register.SB; + } + + if (level - address.getLevel() <= 6) { + return Register.values()[Register.LB.ordinal() + level - address.getLevel()]; // LB|L1|...|L6 + } + + // _errorReporter.ReportRestriction("can't access data more than 6 levels out"); + return Register.L6; // to allow code generation to continue + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java new file mode 100644 index 0000000..3896e32 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/AddressableEntity.java @@ -0,0 +1,29 @@ +package triangle.codeGenerator.entities; + +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public abstract class AddressableEntity extends RuntimeEntity implements FetchableEntity { + + protected final ObjectAddress address; + + protected AddressableEntity(int size, int level, int displacement) { + super(size); + address = new ObjectAddress(level, displacement); + } + + protected AddressableEntity(int size, Frame frame) { + this(size, frame.getLevel(), frame.getSize()); + } + + public ObjectAddress getAddress() { + return address; + } + + public abstract void encodeStore(Emitter emitter, Frame frame, int size, Vname vname); + + public abstract void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname); + + public abstract void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname); +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java new file mode 100644 index 0000000..6c86baf --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/EqualityRoutine.java @@ -0,0 +1,46 @@ +/* + * @(#)EqualityRoutine.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class EqualityRoutine extends RuntimeEntity implements RoutineEntity { + + private final Primitive primitive; + + public EqualityRoutine(int size, Primitive primitive) { + super(size); + this.primitive = primitive; + } + + public final Primitive getPrimitive() { + return primitive; + } + + public void encodeCall(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOADL, frame.getSize() / 2); + emitter.emit(OpCode.CALL, Register.PB, primitive); + } + + public void encodeFetch(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOADA, 0, Register.SB, 0); + emitter.emit(OpCode.LOADA, Register.PB, primitive); + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java new file mode 100644 index 0000000..1e4194c --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/FetchableEntity.java @@ -0,0 +1,11 @@ +package triangle.codeGenerator.entities; + +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public interface FetchableEntity { + + void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname); + +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java new file mode 100644 index 0000000..2354136 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/Field.java @@ -0,0 +1,29 @@ +/* + * @(#)Field.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +public class Field extends RuntimeEntity { + + private final int fieldOffset; + + public Field(int size, int fieldOffset) { + super(size); + this.fieldOffset = fieldOffset; + } + + public final int getFieldOffset() { + return fieldOffset; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java new file mode 100644 index 0000000..e62879e --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownAddress.java @@ -0,0 +1,62 @@ +/* + * @(#)KnownAddress.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class KnownAddress extends AddressableEntity { + + public KnownAddress(int size, int level, int displacement) { + super(size, level, displacement); + } + + public KnownAddress(int size, Frame frame) { + super(size, frame); + } + + public void encodeStore(Emitter emitter, Frame frame, int size, Vname vname) { + if (vname.indexed) { + emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + emitter.emit(OpCode.STOREI, size, 0); + } else { + emitter.emit(OpCode.STORE, size, frame.getDisplayRegister(address), + address.getDisplacement() + vname.offset); + } + } + + public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) { + if (vname.indexed) { + emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + emitter.emit(OpCode.LOADI, size, 0); + } else { + emitter.emit(OpCode.LOAD, size, frame.getDisplayRegister(address), + address.getDisplacement() + vname.offset); + } + } + + public void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname) { + emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset); + if (vname.indexed) { + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java new file mode 100644 index 0000000..4adca41 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownRoutine.java @@ -0,0 +1,44 @@ +/* + * @(#)KnownRoutine.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Register; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class KnownRoutine extends RuntimeEntity implements RoutineEntity { + + private final ObjectAddress address; + + public KnownRoutine(int size, int level, int displacement) { + super(size); + address = new ObjectAddress(level, displacement); + } + + public final ObjectAddress getAddress() { + return address; + } + + public void encodeCall(Emitter emitter, Frame frame) { + emitter.emit(OpCode.CALL, frame.getDisplayRegister(address), Register.CB, address.getDisplacement()); + } + + public void encodeFetch(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOADA, frame.getDisplayRegister(address), 0); + emitter.emit(OpCode.LOADA, Register.CB, address.getDisplacement()); + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java new file mode 100644 index 0000000..af24be5 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/KnownValue.java @@ -0,0 +1,39 @@ +/* + * @(#)KnownValue.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class KnownValue extends RuntimeEntity implements FetchableEntity { + + private final int value; + + public KnownValue(int size, int value) { + super(size); + this.value = value; + } + + public final int getValue() { + return value; + } + + public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) { + // presumably offset = 0 and indexed = false + emitter.emit(OpCode.LOADL, 0, value); + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java new file mode 100644 index 0000000..7440c68 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/ObjectAddress.java @@ -0,0 +1,35 @@ +/* + * @(#)ObjectAddress.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +public class ObjectAddress { + + private final int level; + + private final int displacement; + + public ObjectAddress(int level, int displacement) { + this.level = level; + this.displacement = displacement; + } + + public final int getLevel() { + return level; + } + + public int getDisplacement() { + return displacement; + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java new file mode 100644 index 0000000..4cf3237 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/PrimitiveRoutine.java @@ -0,0 +1,47 @@ +/* + * @(#)PrimitiveRoutine.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class PrimitiveRoutine extends RuntimeEntity implements RoutineEntity { + + private final Primitive primitive; + + public PrimitiveRoutine(int size, Primitive primitive) { + super(size); + this.primitive = primitive; + } + + public final Primitive getPrimitive() { + return primitive; + } + + public void encodeCall(Emitter emitter, Frame frame) { + if (primitive != Primitive.ID) { + emitter.emit(OpCode.CALL, Register.PB, primitive); + } + } + + public void encodeFetch(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOADA, 0, Register.SB, 0); + emitter.emit(OpCode.LOADA, Register.PB, primitive); + } + +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java new file mode 100644 index 0000000..386aef5 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RoutineEntity.java @@ -0,0 +1,11 @@ +package triangle.codeGenerator.entities; + +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public interface RoutineEntity { + + void encodeCall(Emitter emitter, Frame frame); + + void encodeFetch(Emitter emitter, Frame frame); +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java new file mode 100644 index 0000000..14540ee --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/RuntimeEntity.java @@ -0,0 +1,30 @@ +/* + * @(#)RuntimeEntity.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +// Run-time object + +public abstract class RuntimeEntity { + + private final int size; + + protected RuntimeEntity(int size) { + this.size = size; + } + + public final int getSize() { + return size; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java new file mode 100644 index 0000000..1827025 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/TypeRepresentation.java @@ -0,0 +1,23 @@ +/* + * @(#)TypeRepresentation.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +public class TypeRepresentation extends RuntimeEntity { + + public TypeRepresentation(int size) { + super(size); + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java new file mode 100644 index 0000000..af45996 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownAddress.java @@ -0,0 +1,74 @@ +/* + * @(#)UnknownAddress.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.Machine; +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class UnknownAddress extends AddressableEntity { + + public UnknownAddress(int size, int level, int displacement) { + super(size, level, displacement); + } + + public void encodeStore(Emitter emitter, Frame frame, int size, Vname vname) { + + emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement()); + if (vname.indexed) { + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + + int offset = vname.offset; + if (offset != 0) { + emitter.emit(OpCode.LOADL, 0, offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + emitter.emit(OpCode.STOREI, size, 0); + } + + public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) { + emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement()); + + if (vname.indexed) { + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + + int offset = vname.offset; + if (offset != 0) { + emitter.emit(OpCode.LOADL, offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + emitter.emit(OpCode.LOADI, size); + } + + public void encodeFetchAddress(Emitter emitter, Frame frame, Vname vname) { + + emitter.emit(OpCode.LOAD, Machine.addressSize, frame.getDisplayRegister(address), address.getDisplacement()); + if (vname.indexed) { + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + + int offset = vname.offset; + if (offset != 0) { + emitter.emit(OpCode.LOADL, offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + } + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java new file mode 100644 index 0000000..bb7fe26 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownRoutine.java @@ -0,0 +1,44 @@ +/* + * @(#)UnknownRoutine.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.Machine; +import triangle.abstractMachine.OpCode; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class UnknownRoutine extends RuntimeEntity implements RoutineEntity { + + private final ObjectAddress address; + + public UnknownRoutine(int size, int level, int displacement) { + super(size); + address = new ObjectAddress(level, displacement); + } + + public final ObjectAddress getAddress() { + return address; + } + + public void encodeCall(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOAD, Machine.closureSize, frame.getDisplayRegister(address), address.getDisplacement()); + emitter.emit(OpCode.CALLI, 0); + } + + public void encodeFetch(Emitter emitter, Frame frame) { + emitter.emit(OpCode.LOAD, Machine.closureSize, frame.getDisplayRegister(address), address.getDisplacement()); + } + +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java new file mode 100644 index 0000000..7f4442f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/codeGenerator/entities/UnknownValue.java @@ -0,0 +1,51 @@ +/* + * @(#)UnknownValue.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.codeGenerator.entities; + +import triangle.abstractMachine.OpCode; +import triangle.abstractMachine.Primitive; +import triangle.abstractMachine.Register; +import triangle.abstractSyntaxTrees.vnames.Vname; +import triangle.codeGenerator.Emitter; +import triangle.codeGenerator.Frame; + +public class UnknownValue extends RuntimeEntity implements FetchableEntity { + + private final ObjectAddress address; + + public UnknownValue(int size, int level, int displacement) { + super(size); + address = new ObjectAddress(level, displacement); + } + + public UnknownValue(int size, Frame frame) { + this(size, frame.getLevel(), frame.getSize()); + } + + public final ObjectAddress getAddress() { + return address; + } + + public void encodeFetch(Emitter emitter, Frame frame, int size, Vname vname) { + if (vname.indexed) { + emitter.emit(OpCode.LOADA, 0, frame.getDisplayRegister(address), address.getDisplacement() + vname.offset); + emitter.emit(OpCode.CALL, Register.PB, Primitive.ADD); + emitter.emit(OpCode.LOADI, size, 0); + } else { + emitter.emit(OpCode.LOAD, size, frame.getDisplayRegister(address), + address.getDisplacement() + vname.offset); + } + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java new file mode 100644 index 0000000..863b992 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/Checker.java @@ -0,0 +1,980 @@ +/* + * @(#)Checker.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.contextualAnalyzer; + +import triangle.ErrorReporter; +import triangle.StdEnvironment; +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.Program; +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstantDeclaration; +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.FunctionDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcedureDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.declarations.VariableDeclaration; +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.EmptyExpression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FormalParameter; +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.terminals.Terminal; +import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; +import triangle.abstractSyntaxTrees.types.CharTypeDenoter; +import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; +import triangle.abstractSyntaxTrees.types.FieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.IntTypeDenoter; +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; +import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; +import triangle.syntacticAnalyzer.SourcePosition; + +public final class Checker implements ActualParameterVisitor, + ActualParameterSequenceVisitor, ArrayAggregateVisitor, + CommandVisitor, DeclarationVisitor, ExpressionVisitor, + FormalParameterSequenceVisitor, IdentifierVisitor, + LiteralVisitor, OperatorVisitor, ProgramVisitor, + RecordAggregateVisitor, TypeDenoterVisitor, + VnameVisitor { + + // Commands + + // Always returns null. Does not use the given object. + + @Override + public Void visitAssignCommand(AssignCommand ast, Void arg) { + var vType = ast.V.visit(this); + var eType = ast.E.visit(this); + + checkAndReportError(ast.V.variable, "LHS of assignment is not a variable", ast.V); + checkAndReportError(eType.equals(vType), "assignment incompatibilty", ast); + + return null; + } + + @Override + public Void visitCallCommand(CallCommand ast, Void arg) { + var binding = ast.I.visit(this); + + if (binding instanceof ProcedureDeclaration) { + ProcedureDeclaration procedure = (ProcedureDeclaration)binding; + ast.APS.visit(this, procedure.getFormals()); + } else { + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier"); + } + + return null; + } + + @Override + public Void visitEmptyCommand(EmptyCommand ast, Void arg) { + return null; + } + + @Override + public Void visitIfCommand(IfCommand ast, Void arg) { + var eType = ast.E.visit(this); + + checkAndReportError(eType.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E); + + ast.C1.visit(this); + ast.C2.visit(this); + + return null; + } + + @Override + public Void visitLetCommand(LetCommand ast, Void arg) { + idTable.openScope(); + ast.D.visit(this); + ast.C.visit(this); + idTable.closeScope(); + return null; + } + + @Override + public Void visitSequentialCommand(SequentialCommand ast, Void arg) { + ast.C1.visit(this); + ast.C2.visit(this); + return null; + } + + @Override + public Void visitWhileCommand(WhileCommand ast, Void arg) { + var eType = ast.E.visit(this); + + checkAndReportError(eType.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E); + ast.C.visit(this); + + return null; + } + + // Expressions + + // Returns the TypeDenoter denoting the type of the expression. Does + // not use the given object. + + @Override + public TypeDenoter visitArrayExpression(ArrayExpression ast, Void arg) { + var elemType = ast.AA.visit(this); + var il = new IntegerLiteral(Integer.toString(ast.AA.elemCount), ast.getPosition()); + ast.type = new ArrayTypeDenoter(il, elemType, ast.getPosition()); + return ast.type; + } + + @Override + public TypeDenoter visitBinaryExpression(BinaryExpression ast, Void arg) { + var e1Type = ast.E1.visit(this); + var e2Type = ast.E2.visit(this); + var binding = ast.O.visit(this); + + if (binding instanceof BinaryOperatorDeclaration) { + BinaryOperatorDeclaration bbinding = (BinaryOperatorDeclaration)binding; + if (bbinding.ARG1 == StdEnvironment.anyType) { + // this operator must be "=" or "\=" + checkAndReportError(e1Type.equals(e2Type), "incompatible argument types for \"%\"", ast.O, ast); + } else { + checkAndReportError(e1Type.equals(bbinding.ARG1), "wrong argument type for \"%\"", ast.O, ast.E1); + checkAndReportError(e2Type.equals(bbinding.ARG2), "wrong argument type for \"%\"", ast.O, ast.E2); + } + return ast.type = bbinding.RES; + } + + reportUndeclaredOrError(binding, ast.O, "\"%\" is not a binary operator"); + return ast.type = StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitCallExpression(CallExpression ast, Void arg) { + var binding = ast.I.visit(this); + + if (binding instanceof FunctionDeclaration) { + FunctionDeclaration function = (FunctionDeclaration)binding; + ast.APS.visit(this, function.getFormals()); + return ast.type = function.getType(); + } + + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a function identifier"); + return ast.type = StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitCharacterExpression(CharacterExpression ast, Void arg) { + return ast.type = StdEnvironment.charType; + } + + @Override + public TypeDenoter visitEmptyExpression(EmptyExpression ast, Void arg) { + return ast.type = null; + } + + @Override + public TypeDenoter visitIfExpression(IfExpression ast, Void arg) { + var e1Type = ast.E1.visit(this); + checkAndReportError(e1Type.equals(StdEnvironment.booleanType), "Boolean expression expected here", ast.E1); + + var e2Type = ast.E2.visit(this); + var e3Type = ast.E3.visit(this); + checkAndReportError(e2Type.equals(e3Type), "incompatible limbs in if-expression", ast); + return ast.type = e2Type; + } + + @Override + public TypeDenoter visitIntegerExpression(IntegerExpression ast, Void arg) { + return ast.type = StdEnvironment.integerType; + } + + @Override + public TypeDenoter visitLetExpression(LetExpression ast, Void arg) { + idTable.openScope(); + ast.D.visit(this); + ast.type = ast.E.visit(this); + idTable.closeScope(); + return ast.type; + } + + @Override + public TypeDenoter visitRecordExpression(RecordExpression ast, Void arg) { + var rType = ast.RA.visit(this); + return ast.type = new RecordTypeDenoter(rType, ast.getPosition()); + } + + @Override + public TypeDenoter visitUnaryExpression(UnaryExpression ast, Void arg) { + var eType = ast.E.visit(this); + var binding = ast.O.visit(this); + + if (binding instanceof UnaryOperatorDeclaration) { + UnaryOperatorDeclaration ubinding = (UnaryOperatorDeclaration)binding; + checkAndReportError(eType.equals(ubinding.ARG), "wrong argument type for \"%\"", ast.O); + return ast.type = ubinding.RES; + } + + reportUndeclaredOrError(binding, ast.O, "\"%\" is not a unary operator"); + return ast.type = StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitVnameExpression(VnameExpression ast, Void arg) { + return ast.type = ast.V.visit(this); + } + + // Declarations + + // Always returns null. Does not use the given object. + @Override + public Void visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void arg) { + return null; + } + + @Override + public Void visitConstDeclaration(ConstDeclaration ast, Void arg) { + ast.E.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast); + return null; + } + + @Override + public Void visitFuncDeclaration(FuncDeclaration ast, Void arg) { + ast.T = ast.T.visit(this); + // permits recursion + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast); + + idTable.openScope(); + ast.FPS.visit(this); + var eType = ast.E.visit(this); + idTable.closeScope(); + + checkAndReportError(ast.T.equals(eType), "body of function \"%\" has wrong type", ast.I, ast.E); + return null; + } + + @Override + public Void visitProcDeclaration(ProcDeclaration ast, Void arg) { + // permits recursion + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast); + + idTable.openScope(); + ast.FPS.visit(this); + ast.C.visit(this); + idTable.closeScope(); + + return null; + } + + @Override + public Void visitSequentialDeclaration(SequentialDeclaration ast, Void arg) { + ast.D1.visit(this); + ast.D2.visit(this); + return null; + } + + @Override + public Void visitTypeDeclaration(TypeDeclaration ast, Void arg) { + ast.T = ast.T.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast); + return null; + } + + @Override + public Void visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void arg) { + return null; + } + + @Override + public Void visitVarDeclaration(VarDeclaration ast, Void arg) { + ast.T = ast.T.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "identifier \"%\" already declared", ast.I, ast); + return null; + } + + // Array Aggregates + + // Returns the TypeDenoter for the Array Aggregate. Does not use the + // given object. + + @Override + public TypeDenoter visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void arg) { + var eType = ast.E.visit(this); + var elemType = ast.AA.visit(this); + ast.elemCount = ast.AA.elemCount + 1; + checkAndReportError(eType.equals(elemType), "incompatible array-aggregate element", ast.E); + return elemType; + } + + @Override + public TypeDenoter visitSingleArrayAggregate(SingleArrayAggregate ast, Void arg) { + var elemType = ast.E.visit(this); + ast.elemCount = 1; + return elemType; + } + + // Record Aggregates + + // Returns the TypeDenoter for the Record Aggregate. Does not use the + // given object. + + @Override + public FieldTypeDenoter visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void arg) { + var eType = ast.E.visit(this); + var rType = ast.RA.visit(this); + var fType = checkFieldIdentifier(rType, ast.I); + checkAndReportError(fType.equals(StdEnvironment.errorType), "duplicate field \"%\" in record", ast.I); + return ast.type = new MultipleFieldTypeDenoter(ast.I, eType, rType, ast.getPosition()); + } + + @Override + public FieldTypeDenoter visitSingleRecordAggregate(SingleRecordAggregate ast, Void arg) { + var eType = ast.E.visit(this); + return ast.type = new SingleFieldTypeDenoter(ast.I, eType, ast.getPosition()); + } + + // Formal Parameters + + // Always returns null. Does not use the given object. + + @Override + public Void visitConstFormalParameter(ConstFormalParameter ast, Void arg) { + ast.T = ast.T.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast); + return null; + } + + @Override + public Void visitFuncFormalParameter(FuncFormalParameter ast, Void arg) { + idTable.openScope(); + ast.FPS.visit(this); + idTable.closeScope(); + ast.T = ast.T.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast); + return null; + } + + @Override + public Void visitProcFormalParameter(ProcFormalParameter ast, Void arg) { + idTable.openScope(); + ast.FPS.visit(this); + idTable.closeScope(); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast); + return null; + } + + @Override + public Void visitVarFormalParameter(VarFormalParameter ast, Void arg) { + ast.T = ast.T.visit(this); + idTable.enter(ast.I.spelling, ast); + checkAndReportError(!ast.duplicated, "duplicated formal parameter \"%\"", ast.I, ast); + return null; + } + + @Override + public Void visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void arg) { + return null; + } + + @Override + public Void visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void arg) { + ast.FP.visit(this); + ast.FPS.visit(this); + return null; + } + + @Override + public Void visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void arg) { + ast.FP.visit(this); + return null; + } + + // Actual Parameters + + // Always returns null. Uses the given FormalParameter. + + @Override + public Void visitConstActualParameter(ConstActualParameter ast, FormalParameter arg) { + var eType = ast.E.visit(this); + if (arg instanceof ConstFormalParameter) { + ConstFormalParameter param = (ConstFormalParameter)arg; + checkAndReportError(eType.equals(((ConstFormalParameter)arg).T), "wrong type for const actual parameter", ast.E); + } else { + reportError("const actual parameter not expected here", ast); + } + return null; + } + + @Override + public Void visitFuncActualParameter(FuncActualParameter ast, FormalParameter arg) { + var binding = ast.I.visit(this); + if (binding instanceof FunctionDeclaration) { + FunctionDeclaration function = (FunctionDeclaration)binding; + var formals = function.getFormals(); + var functionType = function.getType(); + if (arg instanceof FuncFormalParameter) { + FuncFormalParameter param = (FuncFormalParameter)arg; + if (!formals.equals(param.getFormals())) { + reportError("wrong signature for function \"%\"", ast.I); + } else if (!functionType.equals(param.T)) { + reportError("wrong type for function \"%\"", ast.I); + } + } else { + reportError("func actual parameter not expected here", ast); + } + } else { + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a function identifier"); + } + return null; + } + + @Override + public Void visitProcActualParameter(ProcActualParameter ast, FormalParameter arg) { + var binding = ast.I.visit(this); + if (binding instanceof ProcedureDeclaration) { + ProcedureDeclaration procedure = (ProcedureDeclaration)binding; + var formals = procedure.getFormals(); + if (arg instanceof ProcFormalParameter) { + ProcFormalParameter param = (ProcFormalParameter)arg; + checkAndReportError(formals.equals(param.getFormals()), "wrong signature for procedure \"%\"", ast.I); + } else { + reportError("proc actual parameter not expected here", ast); + } + } else { + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier"); + } + return null; + } + + @Override + public Void visitVarActualParameter(VarActualParameter ast, FormalParameter arg) { + var vType = ast.V.visit(this); + if (!ast.V.variable) { + reportError("actual parameter is not a variable", ast.V); + } else if (arg instanceof VarFormalParameter) { + VarFormalParameter parameter = (VarFormalParameter)arg; + checkAndReportError(vType.equals(parameter.T), "wrong type for var actual parameter", ast.V); + } else { + reportError("var actual parameter not expected here", ast.V); + } + return null; + } + + @Override + public Void visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, FormalParameterSequence arg) { + checkAndReportError(arg instanceof EmptyFormalParameterSequence, "too few actual parameters", ast); + return null; + } + + @Override + public Void visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, FormalParameterSequence arg) { + if (arg instanceof MultipleFormalParameterSequence) { + MultipleFormalParameterSequence formals = (MultipleFormalParameterSequence)arg; + ast.AP.visit(this, formals.FP); + ast.APS.visit(this, formals.FPS); + } else { + reportError("too many actual parameters", ast); + } + return null; + } + + @Override + public Void visitSingleActualParameterSequence(SingleActualParameterSequence ast, FormalParameterSequence arg) { + if (arg instanceof SingleFormalParameterSequence) { + SingleFormalParameterSequence formal = (SingleFormalParameterSequence)arg; + ast.AP.visit(this, formal.FP); + } else { + reportError("incorrect number of actual parameters", ast); + } + return null; + } + + // Type Denoters + + // Returns the expanded version of the TypeDenoter. Does not + // use the given object. + + @Override + public TypeDenoter visitAnyTypeDenoter(AnyTypeDenoter ast, Void arg) { + return StdEnvironment.anyType; + } + + @Override + public TypeDenoter visitArrayTypeDenoter(ArrayTypeDenoter ast, Void arg) { + ast.T = ast.T.visit(this); + checkAndReportError(ast.IL.getValue() != 0, "arrays must not be empty", ast.IL); + return ast; + } + + @Override + public TypeDenoter visitBoolTypeDenoter(BoolTypeDenoter ast, Void arg) { + return StdEnvironment.booleanType; + } + + @Override + public TypeDenoter visitCharTypeDenoter(CharTypeDenoter ast, Void arg) { + return StdEnvironment.charType; + } + + @Override + public TypeDenoter visitErrorTypeDenoter(ErrorTypeDenoter ast, Void arg) { + return StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) { + var binding = ast.I.visit(this); + if (binding instanceof TypeDeclaration) { + TypeDeclaration decl = (TypeDeclaration)binding; + return decl.T; + } + + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a type identifier"); + return StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitIntTypeDenoter(IntTypeDenoter ast, Void arg) { + return StdEnvironment.integerType; + } + + @Override + public TypeDenoter visitRecordTypeDenoter(RecordTypeDenoter ast, Void arg) { + ast.FT = (FieldTypeDenoter) ast.FT.visit(this); + return ast; + } + + @Override + public TypeDenoter visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void arg) { + ast.T = ast.T.visit(this); + ast.FT.visit(this); + return ast; + } + + @Override + public TypeDenoter visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void arg) { + ast.T = ast.T.visit(this); + return ast; + } + + // Literals, Identifiers and Operators + @Override + public TypeDenoter visitCharacterLiteral(CharacterLiteral CL, Void arg) { + return StdEnvironment.charType; + } + + @Override + public Declaration visitIdentifier(Identifier I, Void arg) { + var binding = idTable.retrieve(I.spelling); + if (binding != null) { + I.decl = binding; + } + return binding; + } + + @Override + public TypeDenoter visitIntegerLiteral(IntegerLiteral IL, Void arg) { + return StdEnvironment.integerType; + } + + @Override + public Declaration visitOperator(Operator O, Void arg) { + var binding = idTable.retrieve(O.spelling); + if (binding != null) { + O.decl = binding; + } + return binding; + } + + // Value-or-variable names + + // Determines the address of a named object (constant or variable). + // This consists of a base object, to which 0 or more field-selection + // or array-indexing operations may be applied (if it is a record or + // array). As much as possible of the address computation is done at + // compile-time. Code is generated only when necessary to evaluate + // index expressions at run-time. + // currentLevel is the routine level where the v-name occurs. + // frameSize is the anticipated size of the local stack frame when + // the object is addressed at run-time. + // It returns the description of the base object. + // offset is set to the total of any field offsets (plus any offsets + // due to index expressions that happen to be literals). + // indexed is set to true iff there are any index expressions (other + // than literals). In that case code is generated to compute the + // offset due to these indexing operations at run-time. + + // Returns the TypeDenoter of the Vname. Does not use the + // given object. + + @Override + public TypeDenoter visitDotVname(DotVname ast, Void arg) { + ast.type = null; + var vType = ast.V.visit(this); + ast.variable = ast.V.variable; + if (vType instanceof RecordTypeDenoter) { + RecordTypeDenoter record = (RecordTypeDenoter)vType; + ast.type = checkFieldIdentifier(record.FT, ast.I); + checkAndReportError(ast.type != StdEnvironment.errorType, "no field \"%\" in this record type", + ast.I); + } else { + reportError("record expected here", ast.V); + } + return ast.type; + } + + @Override + public TypeDenoter visitSimpleVname(SimpleVname ast, Void arg) { + ast.variable = false; + ast.type = StdEnvironment.errorType; + + var binding = ast.I.visit(this); + if (binding instanceof ConstantDeclaration) { + ConstantDeclaration constant = (ConstantDeclaration)binding; + ast.variable = false; + return ast.type = constant.getType(); + } else if (binding instanceof VariableDeclaration) { + VariableDeclaration variable = (VariableDeclaration)binding; + ast.variable = true; + return ast.type = variable.getType(); + } + + reportUndeclaredOrError(binding, ast.I, "\"%\" is not a const or var identifier"); + return ast.type = StdEnvironment.errorType; + } + + @Override + public TypeDenoter visitSubscriptVname(SubscriptVname ast, Void arg) { + var vType = ast.V.visit(this); + ast.variable = ast.V.variable; + + var eType = ast.E.visit(this); + if (vType != StdEnvironment.errorType) { + if (vType instanceof ArrayTypeDenoter) { + ArrayTypeDenoter arrayType = (ArrayTypeDenoter)vType; + checkAndReportError(eType.equals(StdEnvironment.integerType), "Integer expression expected here", + ast.E); + ast.type = arrayType.T; + } else { + reportError("array expected here", ast.V); + } + } + + return ast.type; + } + + // Programs + + @Override + public Void visitProgram(Program ast, Void arg) { + ast.C.visit(this); + return null; + } + + // Checks whether the source program, represented by its AST, satisfies the + // language's scope rules and type rules. + // Also decorates the AST as follows: + // (a) Each applied occurrence of an identifier or operator is linked to + // the corresponding declaration of that identifier or operator. + // (b) Each expression and value-or-variable-name is decorated by its type. + // (c) Each type identifier is replaced by the type it denotes. + // Types are represented by small ASTs. + + public void check(Program ast) { + ast.visit(this); + } + + ///////////////////////////////////////////////////////////////////////////// + + public Checker(ErrorReporter reporter) { + this.reporter = reporter; + this.idTable = new IdentificationTable(); + establishStdEnvironment(); + } + + private IdentificationTable idTable; + private static SourcePosition dummyPos = new SourcePosition(); + private ErrorReporter reporter; + + private void reportUndeclaredOrError(Declaration binding, Terminal leaf, String message) { + if (binding == null) { + reportError("\"%\" is not declared", leaf); + } else { + reportError(message, leaf); + } + } + + private void reportError(String message, Terminal ast) { + reportError(message, ast, ast); + } + + private void reportError(String message, Terminal spellingNode, AbstractSyntaxTree positionNode) { + reporter.reportError(message, spellingNode.spelling, positionNode.getPosition()); + } + + private void reportError(String message, AbstractSyntaxTree positionNode) { + reporter.reportError(message, "", positionNode.getPosition()); + } + + private void checkAndReportError(boolean condition, String message, String token, SourcePosition position) { + if (!condition) { + reporter.reportError(message, token, position); + } + } + + private void checkAndReportError(boolean condition, String message, Terminal ast) { + checkAndReportError(condition, message, ast, ast); + } + + private void checkAndReportError(boolean condition, String message, Terminal spellingNode, + AbstractSyntaxTree positionNode) { + checkAndReportError(condition, message, spellingNode.spelling, positionNode.getPosition()); + } + + private void checkAndReportError(boolean condition, String message, AbstractSyntaxTree positionNode) { + checkAndReportError(condition, message, "", positionNode.getPosition()); + } + + private static TypeDenoter checkFieldIdentifier(FieldTypeDenoter ast, Identifier I) { + if (ast instanceof MultipleFieldTypeDenoter) { + MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter)ast; + if (ft.I.spelling.compareTo(I.spelling) == 0) { + I.decl = ast; + return ft.T; + } else { + return checkFieldIdentifier(ft.FT, I); + } + } else if (ast instanceof SingleFieldTypeDenoter) { + SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter)ast; + if (ft.I.spelling.compareTo(I.spelling) == 0) { + I.decl = ast; + return ft.T; + } + } + return StdEnvironment.errorType; + } + + // Creates a small AST to represent the "declaration" of a standard + // type, and enters it in the identification table. + + private TypeDeclaration declareStdType(String id, TypeDenoter typedenoter) { + + var binding = new TypeDeclaration(new Identifier(id, dummyPos), typedenoter, dummyPos); + idTable.enter(id, binding); + return binding; + } + + // Creates a small AST to represent the "declaration" of a standard + // type, and enters it in the identification table. + + private ConstDeclaration declareStdConst(String id, TypeDenoter constType) { + + // constExpr used only as a placeholder for constType + var constExpr = new IntegerExpression(null, dummyPos); + constExpr.type = constType; + var binding = new ConstDeclaration(new Identifier(id, dummyPos), constExpr, dummyPos); + idTable.enter(id, binding); + return binding; + } + + // Creates a small AST to represent the "declaration" of a standard + // type, and enters it in the identification table. + + private ProcDeclaration declareStdProc(String id, FormalParameterSequence fps) { + + var binding = new ProcDeclaration(new Identifier(id, dummyPos), fps, new EmptyCommand(dummyPos), dummyPos); + idTable.enter(id, binding); + return binding; + } + + // Creates a small AST to represent the "declaration" of a standard + // type, and enters it in the identification table. + + private FuncDeclaration declareStdFunc(String id, FormalParameterSequence fps, TypeDenoter resultType) { + + var binding = new FuncDeclaration(new Identifier(id, dummyPos), fps, resultType, new EmptyExpression(dummyPos), + dummyPos); + idTable.enter(id, binding); + return binding; + } + + // Creates a small AST to represent the "declaration" of a + // unary operator, and enters it in the identification table. + // This "declaration" summarises the operator's type info. + + private UnaryOperatorDeclaration declareStdUnaryOp(String op, TypeDenoter argType, TypeDenoter resultType) { + + var binding = new UnaryOperatorDeclaration(new Operator(op, dummyPos), argType, resultType, dummyPos); + idTable.enter(op, binding); + return binding; + } + + // Creates a small AST to represent the "declaration" of a + // binary operator, and enters it in the identification table. + // This "declaration" summarises the operator's type info. + + private BinaryOperatorDeclaration declareStdBinaryOp(String op, TypeDenoter arg1Type, TypeDenoter arg2type, + TypeDenoter resultType) { + + var binding = new BinaryOperatorDeclaration(new Operator(op, dummyPos), arg1Type, arg2type, resultType, + dummyPos); + idTable.enter(op, binding); + return binding; + } + + // Creates small ASTs to represent the standard types. + // Creates small ASTs to represent "declarations" of standard types, + // constants, procedures, functions, and operators. + // Enters these "declarations" in the identification table. + + private final static Identifier dummyI = new Identifier("", dummyPos); + + private void establishStdEnvironment() { + + // idTable.startIdentification(); + StdEnvironment.booleanType = new BoolTypeDenoter(dummyPos); + StdEnvironment.integerType = new IntTypeDenoter(dummyPos); + StdEnvironment.charType = new CharTypeDenoter(dummyPos); + StdEnvironment.anyType = new AnyTypeDenoter(dummyPos); + StdEnvironment.errorType = new ErrorTypeDenoter(dummyPos); + + StdEnvironment.booleanDecl = declareStdType("Boolean", StdEnvironment.booleanType); + StdEnvironment.falseDecl = declareStdConst("false", StdEnvironment.booleanType); + StdEnvironment.trueDecl = declareStdConst("true", StdEnvironment.booleanType); + StdEnvironment.notDecl = declareStdUnaryOp("\\", StdEnvironment.booleanType, StdEnvironment.booleanType); + StdEnvironment.andDecl = declareStdBinaryOp("/\\", StdEnvironment.booleanType, StdEnvironment.booleanType, + StdEnvironment.booleanType); + StdEnvironment.orDecl = declareStdBinaryOp("\\/", StdEnvironment.booleanType, StdEnvironment.booleanType, + StdEnvironment.booleanType); + + StdEnvironment.integerDecl = declareStdType("Integer", StdEnvironment.integerType); + StdEnvironment.maxintDecl = declareStdConst("maxint", StdEnvironment.integerType); + StdEnvironment.addDecl = declareStdBinaryOp("+", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.integerType); + StdEnvironment.subtractDecl = declareStdBinaryOp("-", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.integerType); + StdEnvironment.multiplyDecl = declareStdBinaryOp("*", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.integerType); + StdEnvironment.divideDecl = declareStdBinaryOp("/", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.integerType); + StdEnvironment.moduloDecl = declareStdBinaryOp("//", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.integerType); + StdEnvironment.lessDecl = declareStdBinaryOp("<", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.booleanType); + StdEnvironment.notgreaterDecl = declareStdBinaryOp("<=", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.booleanType); + StdEnvironment.greaterDecl = declareStdBinaryOp(">", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.booleanType); + StdEnvironment.notlessDecl = declareStdBinaryOp(">=", StdEnvironment.integerType, StdEnvironment.integerType, + StdEnvironment.booleanType); + + StdEnvironment.charDecl = declareStdType("Char", StdEnvironment.charType); + StdEnvironment.chrDecl = declareStdFunc("chr", + new SingleFormalParameterSequence( + new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos), + StdEnvironment.charType); + StdEnvironment.ordDecl = declareStdFunc("ord", + new SingleFormalParameterSequence(new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos), + dummyPos), + StdEnvironment.integerType); + StdEnvironment.eofDecl = declareStdFunc("eof", new EmptyFormalParameterSequence(dummyPos), + StdEnvironment.booleanType); + StdEnvironment.eolDecl = declareStdFunc("eol", new EmptyFormalParameterSequence(dummyPos), + StdEnvironment.booleanType); + StdEnvironment.getDecl = declareStdProc("get", new SingleFormalParameterSequence( + new VarFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos)); + StdEnvironment.putDecl = declareStdProc("put", new SingleFormalParameterSequence( + new ConstFormalParameter(dummyI, StdEnvironment.charType, dummyPos), dummyPos)); + StdEnvironment.getintDecl = declareStdProc("getint", new SingleFormalParameterSequence( + new VarFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos)); + StdEnvironment.putintDecl = declareStdProc("putint", new SingleFormalParameterSequence( + new ConstFormalParameter(dummyI, StdEnvironment.integerType, dummyPos), dummyPos)); + StdEnvironment.geteolDecl = declareStdProc("geteol", new EmptyFormalParameterSequence(dummyPos)); + StdEnvironment.puteolDecl = declareStdProc("puteol", new EmptyFormalParameterSequence(dummyPos)); + StdEnvironment.equalDecl = declareStdBinaryOp("=", StdEnvironment.anyType, StdEnvironment.anyType, + StdEnvironment.booleanType); + StdEnvironment.unequalDecl = declareStdBinaryOp("\\=", StdEnvironment.anyType, StdEnvironment.anyType, + StdEnvironment.booleanType); + + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java new file mode 100644 index 0000000..7e6a153 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdEntry.java @@ -0,0 +1,33 @@ +/* + * @(#)IdEntry.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.contextualAnalyzer; + +import triangle.abstractSyntaxTrees.declarations.Declaration; + +public class IdEntry { + + protected String id; + protected Declaration attr; + protected int level; + protected IdEntry previous; + + IdEntry(String id, Declaration attr, int level, IdEntry previous) { + this.id = id; + this.attr = attr; + this.level = level; + this.previous = previous; + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java new file mode 100644 index 0000000..33d1157 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/contextualAnalyzer/IdentificationTable.java @@ -0,0 +1,87 @@ +/* + * @(#)IdentificationTable.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.contextualAnalyzer; + +import triangle.abstractSyntaxTrees.declarations.Declaration; + +public final class IdentificationTable { + + private int level; + private IdEntry latest; + + public IdentificationTable() { + level = 0; + latest = null; + } + + // Opens a new level in the identification table, 1 higher than the + // current topmost level. + + public void openScope() { + level++; + } + + // Closes the topmost level in the identification table, discarding + // all entries belonging to that level. + + public void closeScope() { + // Presumably, idTable.level > 0. + var entry = this.latest; + while (entry.level == this.level) { + entry = entry.previous; + } + + this.level--; + this.latest = entry; + } + + // Makes a new entry in the identification table for the given identifier + // and attribute. The new entry belongs to the current level. + // duplicated is set to to true iff there is already an entry for the + // same identifier at the current level. + + public void enter(String id, Declaration attr) { + attr.duplicated = retrieve(id, true) != null; + this.latest = new IdEntry(id, attr, this.level, this.latest); + } + + // Finds an entry for the given identifier in the identification table, + // if any. If there are several entries for that identifier, finds the + // entry at the highest level, in accordance with the scope rules. + // Returns null iff no entry is found. + // otherwise returns the attribute field of the entry found. + + public Declaration retrieve(String id) { + return retrieve(id, false); + } + + // thisLevelOnly limits the search to only the current level + + public Declaration retrieve(String id, boolean thisLevelOnly) { + var entry = this.latest; + while (true) { + if (entry == null || (thisLevelOnly && entry.level < this.level)) { + break; + } else if (entry.id.equals(id)) { + return entry.attr; + } else { + entry = entry.previous; + } + } + + return null; + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java b/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java new file mode 100644 index 0000000..1ba56ea --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/optimiser/ConstantFolder.java @@ -0,0 +1,599 @@ +package triangle.optimiser; + +import triangle.StdEnvironment; +import triangle.abstractSyntaxTrees.AbstractSyntaxTree; +import triangle.abstractSyntaxTrees.Program; +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.EmptyExpression; +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; +import triangle.abstractSyntaxTrees.types.CharTypeDenoter; +import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; +import triangle.abstractSyntaxTrees.types.IntTypeDenoter; +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; +import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; + +public class ConstantFolder implements ActualParameterVisitor, + ActualParameterSequenceVisitor, ArrayAggregateVisitor, + CommandVisitor, DeclarationVisitor, + ExpressionVisitor, FormalParameterSequenceVisitor, + IdentifierVisitor, LiteralVisitor, + OperatorVisitor, ProgramVisitor, + RecordAggregateVisitor, TypeDenoterVisitor, + VnameVisitor { + { + + } + + @Override + public AbstractSyntaxTree visitConstFormalParameter(ConstFormalParameter ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitFuncFormalParameter(FuncFormalParameter ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitProcFormalParameter(ProcFormalParameter ast, Void arg) { + ast.I.visit(this); + ast.FPS.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitVarFormalParameter(VarFormalParameter ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void arg) { + ast.FT.visit(this); + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitDotVname(DotVname ast, Void arg) { + ast.I.visit(this); + ast.V.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSimpleVname(SimpleVname ast, Void arg) { + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSubscriptVname(SubscriptVname ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.V.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitAnyTypeDenoter(AnyTypeDenoter ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitArrayTypeDenoter(ArrayTypeDenoter ast, Void arg) { + ast.IL.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitBoolTypeDenoter(BoolTypeDenoter ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitCharTypeDenoter(CharTypeDenoter ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitErrorTypeDenoter(ErrorTypeDenoter ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) { + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitIntTypeDenoter(IntTypeDenoter ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitRecordTypeDenoter(RecordTypeDenoter ast, Void arg) { + ast.FT.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.I.visit(this); + ast.RA.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSingleRecordAggregate(SingleRecordAggregate ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitProgram(Program ast, Void arg) { + ast.C.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitOperator(Operator ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitCharacterLiteral(CharacterLiteral ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitIntegerLiteral(IntegerLiteral ast, Void arg) { + return ast; + } + + @Override + public AbstractSyntaxTree visitIdentifier(Identifier ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void arg) { + ast.FP.visit(this); + ast.FPS.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void arg) { + ast.FP.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitArrayExpression(ArrayExpression ast, Void arg) { + ast.AA.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitBinaryExpression(BinaryExpression ast, Void arg) { + AbstractSyntaxTree replacement1 = ast.E1.visit(this); + AbstractSyntaxTree replacement2 = ast.E2.visit(this); + ast.O.visit(this); + + // if visiting a child node returns something, it's either the original constant + // (IntegerLiteral) or a folded version replacing the expression at that child + // node + // If both child nodes are not null; return a folded version of this + // BinaryExpression + // Otherwise, at least one child node isn't constant (foldable) so just replace + // the + // foldable child nodes with their folded equivalent and return null + if (replacement1 != null && replacement2 != null) { + return foldBinaryExpression(replacement1, replacement2, ast.O); + } else if (replacement1 != null) { + ast.E1 = (Expression) replacement1; + } else if (replacement2 != null) { + ast.E2 = (Expression) replacement2; + } + + // if we get here, we can't fold any higher than this level + return null; + } + + @Override + public AbstractSyntaxTree visitCallExpression(CallExpression ast, Void arg) { + ast.APS.visit(this); + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitCharacterExpression(CharacterExpression ast, Void arg) { + ast.CL.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitEmptyExpression(EmptyExpression ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitIfExpression(IfExpression ast, Void arg) { + AbstractSyntaxTree replacement1 = ast.E1.visit(this); + if (replacement1 != null) { + ast.E1 = (Expression) replacement1; + } + AbstractSyntaxTree replacement2 = ast.E2.visit(this); + if (replacement2 != null) { + ast.E2 = (Expression) replacement2; + } + AbstractSyntaxTree replacement3 = ast.E3.visit(this); + if (replacement3 != null) { + ast.E3 = (Expression) replacement3; + } + + return null; + } + + @Override + public AbstractSyntaxTree visitIntegerExpression(IntegerExpression ast, Void arg) { + return ast; + } + + @Override + public AbstractSyntaxTree visitLetExpression(LetExpression ast, Void arg) { + ast.D.visit(this); + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + @Override + public AbstractSyntaxTree visitRecordExpression(RecordExpression ast, Void arg) { + ast.RA.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitUnaryExpression(UnaryExpression ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + + ast.O.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitVnameExpression(VnameExpression ast, Void arg) { + ast.V.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void arg) { + ast.ARG1.visit(this); + ast.ARG2.visit(this); + ast.O.visit(this); + ast.RES.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitConstDeclaration(ConstDeclaration ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitFuncDeclaration(FuncDeclaration ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.FPS.visit(this); + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitProcDeclaration(ProcDeclaration ast, Void arg) { + ast.C.visit(this); + ast.FPS.visit(this); + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSequentialDeclaration(SequentialDeclaration ast, Void arg) { + ast.D1.visit(this); + ast.D2.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitTypeDeclaration(TypeDeclaration ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void arg) { + ast.ARG.visit(this); + ast.O.visit(this); + ast.RES.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitVarDeclaration(VarDeclaration ast, Void arg) { + ast.I.visit(this); + ast.T.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitAssignCommand(AssignCommand ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + ast.V.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitCallCommand(CallCommand ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitEmptyCommand(EmptyCommand ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitIfCommand(IfCommand ast, Void arg) { + ast.C1.visit(this); + ast.C2.visit(this); + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + @Override + public AbstractSyntaxTree visitLetCommand(LetCommand ast, Void arg) { + ast.C.visit(this); + ast.D.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSequentialCommand(SequentialCommand ast, Void arg) { + ast.C1.visit(this); + ast.C2.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitWhileCommand(WhileCommand ast, Void arg) { + ast.C.visit(this); + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + // TODO uncomment if you've implemented the repeat command +// @Override +// public AbstractSyntaxTree visitRepeatCommand(RepeatCommand ast, Void arg) { +// ast.C.visit(this); +// AbstractSyntaxTree replacement = ast.E.visit(this); +// if (replacement != null) { +// ast.E = (Expression) replacement; +// } +// return null; +// } + + @Override + public AbstractSyntaxTree visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void arg) { + ast.AA.visit(this); + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + @Override + public AbstractSyntaxTree visitSingleArrayAggregate(SingleArrayAggregate ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + @Override + public AbstractSyntaxTree visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Void arg) { + return null; + } + + @Override + public AbstractSyntaxTree visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Void arg) { + ast.AP.visit(this); + ast.APS.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitSingleActualParameterSequence(SingleActualParameterSequence ast, Void arg) { + ast.AP.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitConstActualParameter(ConstActualParameter ast, Void arg) { + AbstractSyntaxTree replacement = ast.E.visit(this); + if (replacement != null) { + ast.E = (Expression) replacement; + } + return null; + } + + @Override + public AbstractSyntaxTree visitFuncActualParameter(FuncActualParameter ast, Void arg) { + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitProcActualParameter(ProcActualParameter ast, Void arg) { + ast.I.visit(this); + return null; + } + + @Override + public AbstractSyntaxTree visitVarActualParameter(VarActualParameter ast, Void arg) { + ast.V.visit(this); + return null; + } + + public AbstractSyntaxTree foldBinaryExpression(AbstractSyntaxTree node1, AbstractSyntaxTree node2, Operator o) { + // the only case we know how to deal with for now is two IntegerExpressions + if ((node1 instanceof IntegerExpression) && (node2 instanceof IntegerExpression)) { + int int1 = (Integer.parseInt(((IntegerExpression) node1).IL.spelling)); + int int2 = (Integer.parseInt(((IntegerExpression) node2).IL.spelling)); + Object foldedValue = null; + + if (o.decl == StdEnvironment.addDecl) { + foldedValue = int1 + int2; + } + + if (foldedValue instanceof Integer) { + IntegerLiteral il = new IntegerLiteral(foldedValue.toString(), node1.getPosition()); + IntegerExpression ie = new IntegerExpression(il, node1.getPosition()); + ie.type = StdEnvironment.integerType; + return ie; + } else if (foldedValue instanceof Boolean) { + /* currently not handled! */ + } + } + + // any unhandled situation (i.e., not foldable) is ignored + return null; + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java new file mode 100644 index 0000000..3cccb6b --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Parser.java @@ -0,0 +1,920 @@ +/* + * @(#)Parser.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +import triangle.ErrorReporter; +import triangle.abstractSyntaxTrees.Program; +import triangle.abstractSyntaxTrees.actuals.ActualParameter; +import triangle.abstractSyntaxTrees.actuals.ActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; +import triangle.abstractSyntaxTrees.aggregates.ArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.RecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.Command; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.Declaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.Expression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FormalParameter; +import triangle.abstractSyntaxTrees.formals.FormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.FieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.types.TypeDenoter; +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; +import triangle.abstractSyntaxTrees.vnames.Vname; + +public class Parser { + + private Scanner lexicalAnalyser; + private ErrorReporter errorReporter; + private Token currentToken; + private SourcePosition previousTokenPosition; + + public Parser(Scanner lexer, ErrorReporter reporter) { + lexicalAnalyser = lexer; + errorReporter = reporter; + previousTokenPosition = new SourcePosition(); + } + + // accept checks whether the current token matches tokenExpected. + // If so, fetches the next token. + // If not, reports a syntactic error. + + void accept(int tokenExpected) throws SyntaxError { + if (currentToken.kind == tokenExpected) { + previousTokenPosition = currentToken.position; + currentToken = lexicalAnalyser.scan(); + } else { + syntacticError("\"%\" expected here", Token.spell(tokenExpected)); + } + } + + void acceptIt() { + previousTokenPosition = currentToken.position; + currentToken = lexicalAnalyser.scan(); + } + + // start records the position of the start of a phrase. + // This is defined to be the position of the first + // character of the first token of the phrase. + + void start(SourcePosition position) { + position.start = currentToken.position.start; + } + + // finish records the position of the end of a phrase. + // This is defined to be the position of the last + // character of the last token of the phrase. + + void finish(SourcePosition position) { + position.finish = previousTokenPosition.finish; + } + + void syntacticError(String messageTemplate, String tokenQuoted) throws SyntaxError { + SourcePosition pos = currentToken.position; + errorReporter.reportError(messageTemplate, tokenQuoted, pos); + throw (new SyntaxError()); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // PROGRAMS + // + /////////////////////////////////////////////////////////////////////////////// + + public Program parseProgram() { + + Program programAST = null; + + previousTokenPosition.start = 0; + previousTokenPosition.finish = 0; + currentToken = lexicalAnalyser.scan(); + + try { + Command cAST = parseCommand(); + programAST = new Program(cAST, previousTokenPosition); + if (currentToken.kind != Token.EOT) { + syntacticError("\"%\" not expected after end of program", currentToken.spelling); + } + } catch (SyntaxError s) { + return null; + } + return programAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // LITERALS + // + /////////////////////////////////////////////////////////////////////////////// + + // parseIntegerLiteral parses an integer-literal, and constructs + // a leaf AST to represent it. + + IntegerLiteral parseIntegerLiteral() throws SyntaxError { + IntegerLiteral IL = null; + + if (currentToken.kind == Token.INTLITERAL) { + previousTokenPosition = currentToken.position; + String spelling = currentToken.spelling; + IL = new IntegerLiteral(spelling, previousTokenPosition); + currentToken = lexicalAnalyser.scan(); + } else { + IL = null; + syntacticError("integer literal expected here", ""); + } + return IL; + } + + // parseCharacterLiteral parses a character-literal, and constructs a leaf + // AST to represent it. + + CharacterLiteral parseCharacterLiteral() throws SyntaxError { + CharacterLiteral CL = null; + + if (currentToken.kind == Token.CHARLITERAL) { + previousTokenPosition = currentToken.position; + String spelling = currentToken.spelling; + CL = new CharacterLiteral(spelling, previousTokenPosition); + currentToken = lexicalAnalyser.scan(); + } else { + CL = null; + syntacticError("character literal expected here", ""); + } + return CL; + } + + // parseIdentifier parses an identifier, and constructs a leaf AST to + // represent it. + + Identifier parseIdentifier() throws SyntaxError { + Identifier I = null; + + if (currentToken.kind == Token.IDENTIFIER) { + previousTokenPosition = currentToken.position; + String spelling = currentToken.spelling; + I = new Identifier(spelling, previousTokenPosition); + currentToken = lexicalAnalyser.scan(); + } else { + I = null; + syntacticError("identifier expected here", ""); + } + return I; + } + + // parseOperator parses an operator, and constructs a leaf AST to + // represent it. + + Operator parseOperator() throws SyntaxError { + Operator O = null; + + if (currentToken.kind == Token.OPERATOR) { + previousTokenPosition = currentToken.position; + String spelling = currentToken.spelling; + O = new Operator(spelling, previousTokenPosition); + currentToken = lexicalAnalyser.scan(); + } else { + O = null; + syntacticError("operator expected here", ""); + } + return O; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // COMMANDS + // + /////////////////////////////////////////////////////////////////////////////// + + // parseCommand parses the command, and constructs an AST + // to represent its phrase structure. + + Command parseCommand() throws SyntaxError { + Command commandAST = null; // in case there's a syntactic error + + SourcePosition commandPos = new SourcePosition(); + + start(commandPos); + commandAST = parseSingleCommand(); + while (currentToken.kind == Token.SEMICOLON) { + acceptIt(); + Command c2AST = parseSingleCommand(); + finish(commandPos); + commandAST = new SequentialCommand(commandAST, c2AST, commandPos); + } + return commandAST; + } + + Command parseSingleCommand() throws SyntaxError { + Command commandAST = null; // in case there's a syntactic error + + SourcePosition commandPos = new SourcePosition(); + start(commandPos); + + switch (currentToken.kind) { + + case Token.IDENTIFIER: { + Identifier iAST = parseIdentifier(); + if (currentToken.kind == Token.LPAREN) { + acceptIt(); + ActualParameterSequence apsAST = parseActualParameterSequence(); + accept(Token.RPAREN); + finish(commandPos); + commandAST = new CallCommand(iAST, apsAST, commandPos); + + } else { + + Vname vAST = parseRestOfVname(iAST); + accept(Token.BECOMES); + Expression eAST = parseExpression(); + finish(commandPos); + commandAST = new AssignCommand(vAST, eAST, commandPos); + } + } + break; + + case Token.BEGIN: + acceptIt(); + commandAST = parseCommand(); + accept(Token.END); + break; + + case Token.LET: { + acceptIt(); + Declaration dAST = parseDeclaration(); + accept(Token.IN); + Command cAST = parseSingleCommand(); + finish(commandPos); + commandAST = new LetCommand(dAST, cAST, commandPos); + } + break; + + case Token.IF: { + acceptIt(); + Expression eAST = parseExpression(); + accept(Token.THEN); + Command c1AST = parseSingleCommand(); + accept(Token.ELSE); + Command c2AST = parseSingleCommand(); + finish(commandPos); + commandAST = new IfCommand(eAST, c1AST, c2AST, commandPos); + } + break; + + case Token.WHILE: { + acceptIt(); + Expression eAST = parseExpression(); + accept(Token.DO); + Command cAST = parseSingleCommand(); + finish(commandPos); + commandAST = new WhileCommand(eAST, cAST, commandPos); + } + break; + + case Token.SEMICOLON: + case Token.END: + case Token.ELSE: + case Token.IN: + case Token.EOT: + + finish(commandPos); + commandAST = new EmptyCommand(commandPos); + break; + + default: + syntacticError("\"%\" cannot start a command", currentToken.spelling); + break; + + } + + return commandAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // EXPRESSIONS + // + /////////////////////////////////////////////////////////////////////////////// + + Expression parseExpression() throws SyntaxError { + Expression expressionAST = null; // in case there's a syntactic error + + SourcePosition expressionPos = new SourcePosition(); + + start(expressionPos); + + switch (currentToken.kind) { + + case Token.LET: { + acceptIt(); + Declaration dAST = parseDeclaration(); + accept(Token.IN); + Expression eAST = parseExpression(); + finish(expressionPos); + expressionAST = new LetExpression(dAST, eAST, expressionPos); + } + break; + + case Token.IF: { + acceptIt(); + Expression e1AST = parseExpression(); + accept(Token.THEN); + Expression e2AST = parseExpression(); + accept(Token.ELSE); + Expression e3AST = parseExpression(); + finish(expressionPos); + expressionAST = new IfExpression(e1AST, e2AST, e3AST, expressionPos); + } + break; + + default: + expressionAST = parseSecondaryExpression(); + break; + } + return expressionAST; + } + + Expression parseSecondaryExpression() throws SyntaxError { + Expression expressionAST = null; // in case there's a syntactic error + + SourcePosition expressionPos = new SourcePosition(); + start(expressionPos); + + expressionAST = parsePrimaryExpression(); + while (currentToken.kind == Token.OPERATOR) { + Operator opAST = parseOperator(); + Expression e2AST = parsePrimaryExpression(); + expressionAST = new BinaryExpression(expressionAST, opAST, e2AST, expressionPos); + } + return expressionAST; + } + + Expression parsePrimaryExpression() throws SyntaxError { + Expression expressionAST = null; // in case there's a syntactic error + + SourcePosition expressionPos = new SourcePosition(); + start(expressionPos); + + switch (currentToken.kind) { + + case Token.INTLITERAL: { + IntegerLiteral ilAST = parseIntegerLiteral(); + finish(expressionPos); + expressionAST = new IntegerExpression(ilAST, expressionPos); + } + break; + + case Token.CHARLITERAL: { + CharacterLiteral clAST = parseCharacterLiteral(); + finish(expressionPos); + expressionAST = new CharacterExpression(clAST, expressionPos); + } + break; + + case Token.LBRACKET: { + acceptIt(); + ArrayAggregate aaAST = parseArrayAggregate(); + accept(Token.RBRACKET); + finish(expressionPos); + expressionAST = new ArrayExpression(aaAST, expressionPos); + } + break; + + case Token.LCURLY: { + acceptIt(); + RecordAggregate raAST = parseRecordAggregate(); + accept(Token.RCURLY); + finish(expressionPos); + expressionAST = new RecordExpression(raAST, expressionPos); + } + break; + + case Token.IDENTIFIER: { + Identifier iAST = parseIdentifier(); + if (currentToken.kind == Token.LPAREN) { + acceptIt(); + ActualParameterSequence apsAST = parseActualParameterSequence(); + accept(Token.RPAREN); + finish(expressionPos); + expressionAST = new CallExpression(iAST, apsAST, expressionPos); + + } else { + Vname vAST = parseRestOfVname(iAST); + finish(expressionPos); + expressionAST = new VnameExpression(vAST, expressionPos); + } + } + break; + + case Token.OPERATOR: { + Operator opAST = parseOperator(); + Expression eAST = parsePrimaryExpression(); + finish(expressionPos); + expressionAST = new UnaryExpression(opAST, eAST, expressionPos); + } + break; + + case Token.LPAREN: + acceptIt(); + expressionAST = parseExpression(); + accept(Token.RPAREN); + break; + + default: + syntacticError("\"%\" cannot start an expression", currentToken.spelling); + break; + + } + return expressionAST; + } + + RecordAggregate parseRecordAggregate() throws SyntaxError { + RecordAggregate aggregateAST = null; // in case there's a syntactic error + + SourcePosition aggregatePos = new SourcePosition(); + start(aggregatePos); + + Identifier iAST = parseIdentifier(); + accept(Token.IS); + Expression eAST = parseExpression(); + + if (currentToken.kind == Token.COMMA) { + acceptIt(); + RecordAggregate aAST = parseRecordAggregate(); + finish(aggregatePos); + aggregateAST = new MultipleRecordAggregate(iAST, eAST, aAST, aggregatePos); + } else { + finish(aggregatePos); + aggregateAST = new SingleRecordAggregate(iAST, eAST, aggregatePos); + } + return aggregateAST; + } + + ArrayAggregate parseArrayAggregate() throws SyntaxError { + ArrayAggregate aggregateAST = null; // in case there's a syntactic error + + SourcePosition aggregatePos = new SourcePosition(); + start(aggregatePos); + + Expression eAST = parseExpression(); + if (currentToken.kind == Token.COMMA) { + acceptIt(); + ArrayAggregate aAST = parseArrayAggregate(); + finish(aggregatePos); + aggregateAST = new MultipleArrayAggregate(eAST, aAST, aggregatePos); + } else { + finish(aggregatePos); + aggregateAST = new SingleArrayAggregate(eAST, aggregatePos); + } + return aggregateAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // VALUE-OR-VARIABLE NAMES + // + /////////////////////////////////////////////////////////////////////////////// + + Vname parseVname() throws SyntaxError { + Vname vnameAST = null; // in case there's a syntactic error + Identifier iAST = parseIdentifier(); + vnameAST = parseRestOfVname(iAST); + return vnameAST; + } + + Vname parseRestOfVname(Identifier identifierAST) throws SyntaxError { + SourcePosition vnamePos = new SourcePosition(); + vnamePos = identifierAST.getPosition(); + Vname vAST = new SimpleVname(identifierAST, vnamePos); + + while (currentToken.kind == Token.DOT || currentToken.kind == Token.LBRACKET) { + + if (currentToken.kind == Token.DOT) { + acceptIt(); + Identifier iAST = parseIdentifier(); + vAST = new DotVname(vAST, iAST, vnamePos); + } else { + acceptIt(); + Expression eAST = parseExpression(); + accept(Token.RBRACKET); + finish(vnamePos); + vAST = new SubscriptVname(vAST, eAST, vnamePos); + } + } + return vAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // DECLARATIONS + // + /////////////////////////////////////////////////////////////////////////////// + + Declaration parseDeclaration() throws SyntaxError { + Declaration declarationAST = null; // in case there's a syntactic error + + SourcePosition declarationPos = new SourcePosition(); + start(declarationPos); + declarationAST = parseSingleDeclaration(); + while (currentToken.kind == Token.SEMICOLON) { + acceptIt(); + Declaration d2AST = parseSingleDeclaration(); + finish(declarationPos); + declarationAST = new SequentialDeclaration(declarationAST, d2AST, declarationPos); + } + return declarationAST; + } + + Declaration parseSingleDeclaration() throws SyntaxError { + Declaration declarationAST = null; // in case there's a syntactic error + + SourcePosition declarationPos = new SourcePosition(); + start(declarationPos); + + switch (currentToken.kind) { + + case Token.CONST: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.IS); + Expression eAST = parseExpression(); + finish(declarationPos); + declarationAST = new ConstDeclaration(iAST, eAST, declarationPos); + } + break; + + case Token.VAR: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + finish(declarationPos); + declarationAST = new VarDeclaration(iAST, tAST, declarationPos); + } + break; + + case Token.PROC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.LPAREN); + FormalParameterSequence fpsAST = parseFormalParameterSequence(); + accept(Token.RPAREN); + accept(Token.IS); + Command cAST = parseSingleCommand(); + finish(declarationPos); + declarationAST = new ProcDeclaration(iAST, fpsAST, cAST, declarationPos); + } + break; + + case Token.FUNC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.LPAREN); + FormalParameterSequence fpsAST = parseFormalParameterSequence(); + accept(Token.RPAREN); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + accept(Token.IS); + Expression eAST = parseExpression(); + finish(declarationPos); + declarationAST = new FuncDeclaration(iAST, fpsAST, tAST, eAST, declarationPos); + } + break; + + case Token.TYPE: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.IS); + TypeDenoter tAST = parseTypeDenoter(); + finish(declarationPos); + declarationAST = new TypeDeclaration(iAST, tAST, declarationPos); + } + break; + + default: + syntacticError("\"%\" cannot start a declaration", currentToken.spelling); + break; + + } + return declarationAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // PARAMETERS + // + /////////////////////////////////////////////////////////////////////////////// + + FormalParameterSequence parseFormalParameterSequence() throws SyntaxError { + FormalParameterSequence formalsAST; + + SourcePosition formalsPos = new SourcePosition(); + + start(formalsPos); + if (currentToken.kind == Token.RPAREN) { + finish(formalsPos); + formalsAST = new EmptyFormalParameterSequence(formalsPos); + + } else { + formalsAST = parseProperFormalParameterSequence(); + } + return formalsAST; + } + + FormalParameterSequence parseProperFormalParameterSequence() throws SyntaxError { + FormalParameterSequence formalsAST = null; // in case there's a syntactic error; + + SourcePosition formalsPos = new SourcePosition(); + start(formalsPos); + FormalParameter fpAST = parseFormalParameter(); + if (currentToken.kind == Token.COMMA) { + acceptIt(); + FormalParameterSequence fpsAST = parseProperFormalParameterSequence(); + finish(formalsPos); + formalsAST = new MultipleFormalParameterSequence(fpAST, fpsAST, formalsPos); + + } else { + finish(formalsPos); + formalsAST = new SingleFormalParameterSequence(fpAST, formalsPos); + } + return formalsAST; + } + + FormalParameter parseFormalParameter() throws SyntaxError { + FormalParameter formalAST = null; // in case there's a syntactic error; + + SourcePosition formalPos = new SourcePosition(); + start(formalPos); + + switch (currentToken.kind) { + + case Token.IDENTIFIER: { + Identifier iAST = parseIdentifier(); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + finish(formalPos); + formalAST = new ConstFormalParameter(iAST, tAST, formalPos); + } + break; + + case Token.VAR: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + finish(formalPos); + formalAST = new VarFormalParameter(iAST, tAST, formalPos); + } + break; + + case Token.PROC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.LPAREN); + FormalParameterSequence fpsAST = parseFormalParameterSequence(); + accept(Token.RPAREN); + finish(formalPos); + formalAST = new ProcFormalParameter(iAST, fpsAST, formalPos); + } + break; + + case Token.FUNC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + accept(Token.LPAREN); + FormalParameterSequence fpsAST = parseFormalParameterSequence(); + accept(Token.RPAREN); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + finish(formalPos); + formalAST = new FuncFormalParameter(iAST, fpsAST, tAST, formalPos); + } + break; + + default: + syntacticError("\"%\" cannot start a formal parameter", currentToken.spelling); + break; + + } + return formalAST; + } + + ActualParameterSequence parseActualParameterSequence() throws SyntaxError { + ActualParameterSequence actualsAST; + + SourcePosition actualsPos = new SourcePosition(); + + start(actualsPos); + if (currentToken.kind == Token.RPAREN) { + finish(actualsPos); + actualsAST = new EmptyActualParameterSequence(actualsPos); + + } else { + actualsAST = parseProperActualParameterSequence(); + } + return actualsAST; + } + + ActualParameterSequence parseProperActualParameterSequence() throws SyntaxError { + ActualParameterSequence actualsAST = null; // in case there's a syntactic error + + SourcePosition actualsPos = new SourcePosition(); + + start(actualsPos); + ActualParameter apAST = parseActualParameter(); + if (currentToken.kind == Token.COMMA) { + acceptIt(); + ActualParameterSequence apsAST = parseProperActualParameterSequence(); + finish(actualsPos); + actualsAST = new MultipleActualParameterSequence(apAST, apsAST, actualsPos); + } else { + finish(actualsPos); + actualsAST = new SingleActualParameterSequence(apAST, actualsPos); + } + return actualsAST; + } + + ActualParameter parseActualParameter() throws SyntaxError { + ActualParameter actualAST = null; // in case there's a syntactic error + + SourcePosition actualPos = new SourcePosition(); + + start(actualPos); + + switch (currentToken.kind) { + + case Token.IDENTIFIER: + case Token.INTLITERAL: + case Token.CHARLITERAL: + case Token.OPERATOR: + case Token.LET: + case Token.IF: + case Token.LPAREN: + case Token.LBRACKET: + case Token.LCURLY: { + Expression eAST = parseExpression(); + finish(actualPos); + actualAST = new ConstActualParameter(eAST, actualPos); + } + break; + + case Token.VAR: { + acceptIt(); + Vname vAST = parseVname(); + finish(actualPos); + actualAST = new VarActualParameter(vAST, actualPos); + } + break; + + case Token.PROC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + finish(actualPos); + actualAST = new ProcActualParameter(iAST, actualPos); + } + break; + + case Token.FUNC: { + acceptIt(); + Identifier iAST = parseIdentifier(); + finish(actualPos); + actualAST = new FuncActualParameter(iAST, actualPos); + } + break; + + default: + syntacticError("\"%\" cannot start an actual parameter", currentToken.spelling); + break; + + } + return actualAST; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // TYPE-DENOTERS + // + /////////////////////////////////////////////////////////////////////////////// + + TypeDenoter parseTypeDenoter() throws SyntaxError { + TypeDenoter typeAST = null; // in case there's a syntactic error + SourcePosition typePos = new SourcePosition(); + + start(typePos); + + switch (currentToken.kind) { + + case Token.IDENTIFIER: { + Identifier iAST = parseIdentifier(); + finish(typePos); + typeAST = new SimpleTypeDenoter(iAST, typePos); + } + break; + + case Token.ARRAY: { + acceptIt(); + IntegerLiteral ilAST = parseIntegerLiteral(); + accept(Token.OF); + TypeDenoter tAST = parseTypeDenoter(); + finish(typePos); + typeAST = new ArrayTypeDenoter(ilAST, tAST, typePos); + } + break; + + case Token.RECORD: { + acceptIt(); + FieldTypeDenoter fAST = parseFieldTypeDenoter(); + accept(Token.END); + finish(typePos); + typeAST = new RecordTypeDenoter(fAST, typePos); + } + break; + + default: + syntacticError("\"%\" cannot start a type denoter", currentToken.spelling); + break; + + } + return typeAST; + } + + FieldTypeDenoter parseFieldTypeDenoter() throws SyntaxError { + FieldTypeDenoter fieldAST = null; // in case there's a syntactic error + + SourcePosition fieldPos = new SourcePosition(); + + start(fieldPos); + Identifier iAST = parseIdentifier(); + accept(Token.COLON); + TypeDenoter tAST = parseTypeDenoter(); + if (currentToken.kind == Token.COMMA) { + acceptIt(); + FieldTypeDenoter fAST = parseFieldTypeDenoter(); + finish(fieldPos); + fieldAST = new MultipleFieldTypeDenoter(iAST, tAST, fAST, fieldPos); + } else { + finish(fieldPos); + fieldAST = new SingleFieldTypeDenoter(iAST, tAST, fieldPos); + } + return fieldAST; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java new file mode 100644 index 0000000..4da5ed5 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Scanner.java @@ -0,0 +1,272 @@ +/* + * @(#)Scanner.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +public final class Scanner { + + private SourceFile sourceFile; + private boolean debug; + + private char currentChar; + private StringBuffer currentSpelling; + private boolean currentlyScanningToken; + + private boolean isLetter(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + + private boolean isDigit(char c) { + return (c >= '0' && c <= '9'); + } + + // isOperator returns true iff the given character is an operator character. + + private boolean isOperator(char c) { + return (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '<' || c == '>' || c == '\\' + || c == '&' || c == '@' || c == '%' || c == '^' || c == '?'); + } + + /////////////////////////////////////////////////////////////////////////////// + + public Scanner(SourceFile source) { + sourceFile = source; + currentChar = sourceFile.getSource(); + debug = false; + } + + public void enableDebugging() { + debug = true; + } + + // takeIt appends the current character to the current token, and gets + // the next character from the source program. + + private void takeIt() { + if (currentlyScanningToken) + currentSpelling.append(currentChar); + currentChar = sourceFile.getSource(); + } + + // scanSeparator skips a single separator. + + private void scanSeparator() { + switch (currentChar) { + + // comment + case '!': { + takeIt(); + while ((currentChar != SourceFile.EOL) && (currentChar != SourceFile.EOT)) + takeIt(); + if (currentChar == SourceFile.EOL) + takeIt(); + } + break; + + // whitespace + case ' ': + case '\n': + case '\r': + case '\t': + takeIt(); + break; + } + } + + private int scanToken() { + + switch (currentChar) { + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + takeIt(); + while (isLetter(currentChar) || isDigit(currentChar)) + takeIt(); + return Token.IDENTIFIER; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + takeIt(); + while (isDigit(currentChar)) + takeIt(); + return Token.INTLITERAL; + + case '+': + case '-': + case '*': + case '/': + case '=': + case '<': + case '>': + case '\\': + case '&': + case '@': + case '%': + case '^': + case '?': + takeIt(); + while (isOperator(currentChar)) + takeIt(); + return Token.OPERATOR; + + case '\'': + takeIt(); + takeIt(); // the quoted character + if (currentChar == '\'') { + takeIt(); + return Token.CHARLITERAL; + } else + return Token.ERROR; + + case '.': + takeIt(); + return Token.DOT; + + case ':': + takeIt(); + if (currentChar == '=') { + takeIt(); + return Token.BECOMES; + } else + return Token.COLON; + + case ';': + takeIt(); + return Token.SEMICOLON; + + case ',': + takeIt(); + return Token.COMMA; + + case '~': + takeIt(); + return Token.IS; + + case '(': + takeIt(); + return Token.LPAREN; + + case ')': + takeIt(); + return Token.RPAREN; + + case '[': + takeIt(); + return Token.LBRACKET; + + case ']': + takeIt(); + return Token.RBRACKET; + + case '{': + takeIt(); + return Token.LCURLY; + + case '}': + takeIt(); + return Token.RCURLY; + + case SourceFile.EOT: + return Token.EOT; + + default: + takeIt(); + return Token.ERROR; + } + } + + public Token scan() { + Token tok; + SourcePosition pos; + int kind; + + currentlyScanningToken = false; + // skip any whitespace or comments + while (currentChar == '!' || currentChar == ' ' || currentChar == '\n' || currentChar == '\r' + || currentChar == '\t') + scanSeparator(); + + currentlyScanningToken = true; + currentSpelling = new StringBuffer(""); + pos = new SourcePosition(); + pos.start = sourceFile.getCurrentLine(); + + kind = scanToken(); + + pos.finish = sourceFile.getCurrentLine(); + tok = new Token(kind, currentSpelling.toString(), pos); + if (debug) + System.out.println(tok); + return tok; + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java new file mode 100644 index 0000000..3651455 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourceFile.java @@ -0,0 +1,68 @@ +/* + * @(#)SourceFile.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +import java.net.URL; + +public class SourceFile { + + public static final char EOL = '\n'; + public static final char EOT = '\u0000'; + + java.io.File sourceFile; + java.io.InputStream source; + int currentLine; + + public static SourceFile ofPath(String pathname) { + try { + SourceFile sf = new SourceFile(); + sf.sourceFile = new java.io.File(pathname); + sf.source = new java.io.FileInputStream(sf.sourceFile); + return sf; + } catch (java.io.IOException s) { + return null; + } + } + + public static SourceFile fromResource(String handle) { + SourceFile sf = new SourceFile(); + //sf.sourceFile = new java.io.File(pathname); + sf.source = sf.getClass().getResourceAsStream(handle); + return sf; + } + + private SourceFile() { + currentLine = 1; + } + + char getSource() { + try { + int c = source.read(); + + if (c == -1) { + c = EOT; + } else if (c == EOL) { + currentLine++; + } + return (char) c; + } catch (java.io.IOException s) { + return EOT; + } + } + + int getCurrentLine() { + return currentLine; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java new file mode 100644 index 0000000..fbd5716 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SourcePosition.java @@ -0,0 +1,35 @@ +/* + * @(#)SourcePosition.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +public class SourcePosition { + + public int start, finish; + + public SourcePosition() { + start = 0; + finish = 0; + } + + public SourcePosition(int s, int f) { + start = s; + finish = f; + } + + @Override + public String toString() { + return "(" + start + ", " + finish + ")"; + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java new file mode 100644 index 0000000..1ea031d --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/SyntaxError.java @@ -0,0 +1,29 @@ +/* + * @(#)SyntaxError.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +class SyntaxError extends Exception { + + private static final long serialVersionUID = -5280306336102766860L; + + SyntaxError() { + super(); + } + + SyntaxError(String s) { + super(s); + } + +} diff --git a/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java new file mode 100644 index 0000000..51f3203 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/syntacticAnalyzer/Token.java @@ -0,0 +1,84 @@ +/* + * @(#)Token.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.syntacticAnalyzer; + +final class Token extends Object { + + protected int kind; + protected String spelling; + protected SourcePosition position; + + public Token(int kind, String spelling, SourcePosition position) { + + if (kind == Token.IDENTIFIER) { + int currentKind = firstReservedWord; + boolean searching = true; + + while (searching) { + int comparison = tokenTable[currentKind].compareTo(spelling); + if (comparison == 0) { + this.kind = currentKind; + searching = false; + } else if (comparison > 0 || currentKind == lastReservedWord) { + this.kind = Token.IDENTIFIER; + searching = false; + } else { + currentKind++; + } + } + } else + this.kind = kind; + + this.spelling = spelling; + this.position = position; + + } + + public static String spell(int kind) { + return tokenTable[kind]; + } + + @Override + public String toString() { + return "Kind=" + kind + ", spelling=" + spelling + ", position=" + position; + } + + // Token classes... + + public static final int + + // literals, identifiers, operators... + INTLITERAL = 0, CHARLITERAL = 1, IDENTIFIER = 2, OPERATOR = 3, + + // reserved words - must be in alphabetical order... + ARRAY = 4, BEGIN = 5, CONST = 6, DO = 7, ELSE = 8, END = 9, FUNC = 10, IF = 11, IN = 12, LET = 13, OF = 14, + PROC = 15, RECORD = 16, THEN = 17, TYPE = 18, VAR = 19, WHILE = 20, + + // punctuation... + DOT = 21, COLON = 22, SEMICOLON = 23, COMMA = 24, BECOMES = 25, IS = 26, + + // brackets... + LPAREN = 27, RPAREN = 28, LBRACKET = 29, RBRACKET = 30, LCURLY = 31, RCURLY = 32, + + // special tokens... + EOT = 33, ERROR = 34; + + private static String[] tokenTable = new String[] { "", "", "", "", "array", + "begin", "const", "do", "else", "end", "func", "if", "in", "let", "of", "proc", "record", "then", "type", + "var", "while", ".", ":", ";", ",", ":=", "~", "(", ")", "[", "]", "{", "}", "", "" }; + + private final static int firstReservedWord = Token.ARRAY, lastReservedWord = Token.WHILE; + +} diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java new file mode 100644 index 0000000..53fd82f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Drawer.java @@ -0,0 +1,68 @@ +/* + * @(#)Drawer.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Point; + +import triangle.abstractSyntaxTrees.Program; + +public class Drawer { + + private DrawerFrame frame; + private DrawerPanel panel; + + private Program theAST; + private DrawingTree theDrawing; + + // Draw the AST representing a complete program. + + public void draw(Program ast) { + theAST = ast; + panel = new DrawerPanel(this); + frame = new DrawerFrame(panel); + + Font font = new Font("SansSerif", Font.PLAIN, 12); + frame.setFont(font); + + FontMetrics fontMetrics = frame.getFontMetrics(font); + + // another class of visitor is used for drawing the tree: LayoutVisitor + // LayoutVisitor is passed to the AST which, in turn, calls visitProgram + // and then each AST node is visited. This ultimately constructs a + // DrawingTree, which is structurally the same as the AST but is decorated + // with coordinates (and has only DrawingTree objects as nodes) + // Each DrawingTree object knows how to paint itself, so it's passed to a + // DrawerPanel and DrawerFrame for display + LayoutVisitor layout = new LayoutVisitor(fontMetrics); + theDrawing = (DrawingTree) theAST.visit(layout, null); + theDrawing.position(new Point(2048, 10)); + + frame.setVisible(true); + } + + public void paintAST(Graphics g) { + g.setColor(panel.getBackground()); + Dimension d = panel.getSize(); + g.fillRect(0, 0, d.width, d.height); + + if (theDrawing != null) { + theDrawing.paint(g); + } + } +} diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java new file mode 100644 index 0000000..a939c44 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerFrame.java @@ -0,0 +1,74 @@ +/* + * @(#)DrawerFrame.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +class DrawerFrame extends JFrame { + /** + * + */ + private static final long serialVersionUID = -3650404598416929282L; + + public DrawerFrame(JPanel panel) { + setSize(300, 200); + Toolkit tk = Toolkit.getDefaultToolkit(); + Dimension d = tk.getScreenSize(); + int screenHeight = d.height; + int screenWidth = d.width; + setTitle("Triangle Compiler Abstract Syntax Tree"); + setSize(screenWidth / 2, screenHeight / 2); + setLocation(screenWidth / 4, screenHeight / 4); + // Image img = tk.getImage("icon.gif"); + // setIconImage(img); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + Container contentPane = getContentPane(); + final JScrollPane jScrollPane = new JScrollPane(panel); + + contentPane.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + super.componentResized(e); + jScrollPane.getHorizontalScrollBar().setValue(jScrollPane.getHorizontalScrollBar().getMaximum()); + jScrollPane.getHorizontalScrollBar().setValue(jScrollPane.getHorizontalScrollBar().getValue() / 2); + } + }); + + contentPane.add(jScrollPane); + + } + +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java new file mode 100644 index 0000000..40c3b72 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawerPanel.java @@ -0,0 +1,39 @@ +/* + * @(#)DrawerPanel.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JPanel; + +class DrawerPanel extends JPanel { + /** + * + */ + private static final long serialVersionUID = 565914745506889669L; + private Drawer drawer; + + public DrawerPanel(Drawer drawer) { + setPreferredSize(new Dimension(4096, 4096)); + this.drawer = drawer; + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + drawer.paintAST(g); + } +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java new file mode 100644 index 0000000..742eb6f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/DrawingTree.java @@ -0,0 +1,84 @@ +/* + * @(#)DrawingTree.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; + +public class DrawingTree { + + String caption; + int width, height; + Point pos, offset; + Polygon contour; + DrawingTree parent; + DrawingTree[] children; + + public DrawingTree(String caption, int width, int height) { + this.caption = caption; + this.width = width; + this.height = height; + this.parent = null; + this.children = null; + this.pos = new Point(0, 0); + this.offset = new Point(0, 0); + this.contour = new Polygon(); + } + + public void setChildren(DrawingTree[] children) { + this.children = children; + for (int i = 0; i < children.length; i++) + children[i].parent = this; + } + + private final int FIXED_FONT_HEIGHT = 10; + private final Color nodeColor = new Color(250, 220, 100); + + public void paint(Graphics graphics) { + graphics.setColor(nodeColor); + graphics.fillRect(pos.x, pos.y, width, height); + graphics.setColor(Color.black); + graphics.drawRect(pos.x, pos.y, width - 1, height - 1); + graphics.drawString(caption, pos.x + 2, pos.y + (height + FIXED_FONT_HEIGHT) / 2); + + if (children != null) { + for (DrawingTree child : children) { + child.paint(graphics); + } + } + + if (parent != null) { + graphics.drawLine(pos.x + width / 2, pos.y, parent.pos.x + parent.width / 2, parent.pos.y + parent.height); + } + } + + public void position(Point pos) { + + this.pos.x = pos.x + this.offset.x; + this.pos.y = pos.y + this.offset.y; + + Point temp = new Point(this.pos.x, this.pos.y); + + if (children != null) { + for (DrawingTree child : children) { + child.position(temp); + temp.x += child.offset.x; + temp.y = this.pos.y + children[0].offset.y; + } + } + } + +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java new file mode 100644 index 0000000..dfa4b35 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/LayoutVisitor.java @@ -0,0 +1,680 @@ +/* + * @(#)LayoutVisitor.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +import java.awt.FontMetrics; + +import triangle.abstractSyntaxTrees.Program; +import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; +import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; +import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; +import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; +import triangle.abstractSyntaxTrees.actuals.VarActualParameter; +import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; +import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; +import triangle.abstractSyntaxTrees.commands.AssignCommand; +import triangle.abstractSyntaxTrees.commands.CallCommand; +import triangle.abstractSyntaxTrees.commands.EmptyCommand; +import triangle.abstractSyntaxTrees.commands.IfCommand; +import triangle.abstractSyntaxTrees.commands.LetCommand; +import triangle.abstractSyntaxTrees.commands.SequentialCommand; +import triangle.abstractSyntaxTrees.commands.WhileCommand; +import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; +import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; +import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; +import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; +import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; +import triangle.abstractSyntaxTrees.declarations.VarDeclaration; +import triangle.abstractSyntaxTrees.expressions.ArrayExpression; +import triangle.abstractSyntaxTrees.expressions.BinaryExpression; +import triangle.abstractSyntaxTrees.expressions.CallExpression; +import triangle.abstractSyntaxTrees.expressions.CharacterExpression; +import triangle.abstractSyntaxTrees.expressions.EmptyExpression; +import triangle.abstractSyntaxTrees.expressions.IfExpression; +import triangle.abstractSyntaxTrees.expressions.IntegerExpression; +import triangle.abstractSyntaxTrees.expressions.LetExpression; +import triangle.abstractSyntaxTrees.expressions.RecordExpression; +import triangle.abstractSyntaxTrees.expressions.UnaryExpression; +import triangle.abstractSyntaxTrees.expressions.VnameExpression; +import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; +import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; +import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; +import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; +import triangle.abstractSyntaxTrees.formals.VarFormalParameter; +import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; +import triangle.abstractSyntaxTrees.terminals.Identifier; +import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; +import triangle.abstractSyntaxTrees.terminals.Operator; +import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; +import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; +import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; +import triangle.abstractSyntaxTrees.types.CharTypeDenoter; +import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; +import triangle.abstractSyntaxTrees.types.IntTypeDenoter; +import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; +import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; +import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; +import triangle.abstractSyntaxTrees.types.TypeDeclaration; +import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; +import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.CommandVisitor; +import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; +import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; +import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; +import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; +import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; +import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; +import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; +import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; +import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; +import triangle.abstractSyntaxTrees.visitors.VnameVisitor; +import triangle.abstractSyntaxTrees.vnames.DotVname; +import triangle.abstractSyntaxTrees.vnames.SimpleVname; +import triangle.abstractSyntaxTrees.vnames.SubscriptVname; + +public class LayoutVisitor implements ActualParameterVisitor, + ActualParameterSequenceVisitor, ArrayAggregateVisitor, + CommandVisitor, DeclarationVisitor, ExpressionVisitor, + FormalParameterSequenceVisitor, IdentifierVisitor, + LiteralVisitor, OperatorVisitor, ProgramVisitor, + RecordAggregateVisitor, TypeDenoterVisitor, + VnameVisitor { + + private final int BORDER = 5; + private final int PARENT_SEP = 30; + + private FontMetrics fontMetrics; + + public LayoutVisitor(FontMetrics fontMetrics) { + this.fontMetrics = fontMetrics; + } + + // Commands + @Override + public DrawingTree visitAssignCommand(AssignCommand ast, Void obj) { + var d1 = ast.V.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("AssignCom.", d1, d2); + } + + @Override + public DrawingTree visitCallCommand(CallCommand ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.APS.visit(this); + return layoutBinary("CallCom.", d1, d2); + } + + @Override + public DrawingTree visitEmptyCommand(EmptyCommand ast, Void obj) { + return layoutNullary("EmptyCom."); + } + + @Override + public DrawingTree visitIfCommand(IfCommand ast, Void obj) { + var d1 = ast.E.visit(this); + var d2 = ast.C1.visit(this); + var d3 = ast.C2.visit(this); + return layoutTernary("IfCom.", d1, d2, d3); + } + + @Override + public DrawingTree visitLetCommand(LetCommand ast, Void obj) { + var d1 = ast.D.visit(this); + var d2 = ast.C.visit(this); + return layoutBinary("LetCom.", d1, d2); + } + + @Override + public DrawingTree visitSequentialCommand(SequentialCommand ast, Void obj) { + var d1 = ast.C1.visit(this); + var d2 = ast.C2.visit(this); + return layoutBinary("Seq.Com.", d1, d2); + } + + @Override + public DrawingTree visitWhileCommand(WhileCommand ast, Void obj) { + var d1 = ast.E.visit(this); + var d2 = ast.C.visit(this); + return layoutBinary("WhileCom.", d1, d2); + } + + // Expressions + @Override + public DrawingTree visitArrayExpression(ArrayExpression ast, Void obj) { + var d1 = ast.AA.visit(this); + return layoutUnary("ArrayExpr.", d1); + } + + @Override + public DrawingTree visitBinaryExpression(BinaryExpression ast, Void obj) { + var d1 = ast.E1.visit(this); + var d2 = ast.O.visit(this); + var d3 = ast.E2.visit(this); + return layoutTernary("Bin.Expr.", d1, d2, d3); + } + + @Override + public DrawingTree visitCallExpression(CallExpression ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.APS.visit(this); + return layoutBinary("CallExpr.", d1, d2); + } + + @Override + public DrawingTree visitCharacterExpression(CharacterExpression ast, Void obj) { + var d1 = ast.CL.visit(this); + return layoutUnary("Char.Expr.", d1); + } + + @Override + public DrawingTree visitEmptyExpression(EmptyExpression ast, Void obj) { + return layoutNullary("EmptyExpr."); + } + + @Override + public DrawingTree visitIfExpression(IfExpression ast, Void obj) { + var d1 = ast.E1.visit(this); + var d2 = ast.E2.visit(this); + var d3 = ast.E3.visit(this); + return layoutTernary("IfExpr.", d1, d2, d3); + } + + @Override + public DrawingTree visitIntegerExpression(IntegerExpression ast, Void obj) { + var d1 = ast.IL.visit(this); + return layoutUnary("Int.Expr.", d1); + } + + @Override + public DrawingTree visitLetExpression(LetExpression ast, Void obj) { + var d1 = ast.D.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("LetExpr.", d1, d2); + } + + @Override + public DrawingTree visitRecordExpression(RecordExpression ast, Void obj) { + var d1 = ast.RA.visit(this); + return layoutUnary("Rec.Expr.", d1); + } + + @Override + public DrawingTree visitUnaryExpression(UnaryExpression ast, Void obj) { + var d1 = ast.O.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("UnaryExpr.", d1, d2); + } + + @Override + public DrawingTree visitVnameExpression(VnameExpression ast, Void obj) { + var d1 = ast.V.visit(this); + return layoutUnary("VnameExpr.", d1); + } + + // Declarations + @Override + public DrawingTree visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void obj) { + var d1 = ast.O.visit(this); + var d2 = ast.ARG1.visit(this); + var d3 = ast.ARG2.visit(this); + var d4 = ast.RES.visit(this); + return layoutQuaternary("Bin.Op.Decl.", d1, d2, d3, d4); + } + + @Override + public DrawingTree visitConstDeclaration(ConstDeclaration ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("ConstDecl.", d1, d2); + } + + @Override + public DrawingTree visitFuncDeclaration(FuncDeclaration ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.FPS.visit(this); + var d3 = ast.T.visit(this); + var d4 = ast.E.visit(this); + return layoutQuaternary("FuncDecl.", d1, d2, d3, d4); + } + + @Override + public DrawingTree visitProcDeclaration(ProcDeclaration ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.FPS.visit(this); + var d3 = ast.C.visit(this); + return layoutTernary("ProcDecl.", d1, d2, d3); + } + + @Override + public DrawingTree visitSequentialDeclaration(SequentialDeclaration ast, Void obj) { + var d1 = ast.D1.visit(this); + var d2 = ast.D2.visit(this); + return layoutBinary("Seq.Decl.", d1, d2); + } + + @Override + public DrawingTree visitTypeDeclaration(TypeDeclaration ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("TypeDecl.", d1, d2); + } + + @Override + public DrawingTree visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void obj) { + var d1 = ast.O.visit(this); + var d2 = ast.ARG.visit(this); + var d3 = ast.RES.visit(this); + return layoutTernary("UnaryOp.Decl.", d1, d2, d3); + } + + @Override + public DrawingTree visitVarDeclaration(VarDeclaration ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("VarDecl.", d1, d2); + } + + // Array Aggregates + @Override + public DrawingTree visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void obj) { + var d1 = ast.E.visit(this); + var d2 = ast.AA.visit(this); + return layoutBinary("Mult.ArrayAgg.", d1, d2); + } + + @Override + public DrawingTree visitSingleArrayAggregate(SingleArrayAggregate ast, Void obj) { + var d1 = ast.E.visit(this); + return layoutUnary("Sing.ArrayAgg.", d1); + } + + // Record Aggregates + @Override + public DrawingTree visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.E.visit(this); + var d3 = ast.RA.visit(this); + return layoutTernary("Mult.Rec.Agg.", d1, d2, d3); + } + + @Override + public DrawingTree visitSingleRecordAggregate(SingleRecordAggregate ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("Sing.Rec.Agg.", d1, d2); + } + + // Formal Parameters + @Override + public DrawingTree visitConstFormalParameter(ConstFormalParameter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("ConstF.P.", d1, d2); + } + + @Override + public DrawingTree visitFuncFormalParameter(FuncFormalParameter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.FPS.visit(this); + var d3 = ast.T.visit(this); + return layoutTernary("FuncF.P.", d1, d2, d3); + } + + @Override + public DrawingTree visitProcFormalParameter(ProcFormalParameter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.FPS.visit(this); + return layoutBinary("ProcF.P.", d1, d2); + } + + @Override + public DrawingTree visitVarFormalParameter(VarFormalParameter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("VarF.P.", d1, d2); + } + + @Override + public DrawingTree visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void obj) { + return layoutNullary("EmptyF.P.S."); + } + + @Override + public DrawingTree visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void obj) { + var d1 = ast.FP.visit(this); + var d2 = ast.FPS.visit(this); + return layoutBinary("Mult.F.P.S.", d1, d2); + } + + @Override + public DrawingTree visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void obj) { + var d1 = ast.FP.visit(this); + return layoutUnary("Sing.F.P.S.", d1); + } + + // Actual Parameters + @Override + public DrawingTree visitConstActualParameter(ConstActualParameter ast, Void obj) { + var d1 = ast.E.visit(this); + return layoutUnary("ConstA.P.", d1); + } + + @Override + public DrawingTree visitFuncActualParameter(FuncActualParameter ast, Void obj) { + var d1 = ast.I.visit(this); + return layoutUnary("FuncA.P.", d1); + } + + @Override + public DrawingTree visitProcActualParameter(ProcActualParameter ast, Void obj) { + var d1 = ast.I.visit(this); + return layoutUnary("ProcA.P.", d1); + } + + @Override + public DrawingTree visitVarActualParameter(VarActualParameter ast, Void obj) { + var d1 = ast.V.visit(this); + return layoutUnary("VarA.P.", d1); + } + + @Override + public DrawingTree visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Void obj) { + return layoutNullary("EmptyA.P.S."); + } + + @Override + public DrawingTree visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Void obj) { + var d1 = ast.AP.visit(this); + var d2 = ast.APS.visit(this); + return layoutBinary("Mult.A.P.S.", d1, d2); + } + + @Override + public DrawingTree visitSingleActualParameterSequence(SingleActualParameterSequence ast, Void obj) { + var d1 = ast.AP.visit(this); + return layoutUnary("Sing.A.P.S.", d1); + } + + // Type Denoters + @Override + public DrawingTree visitAnyTypeDenoter(AnyTypeDenoter ast, Void obj) { + return layoutNullary("any"); + } + + @Override + public DrawingTree visitArrayTypeDenoter(ArrayTypeDenoter ast, Void obj) { + var d1 = ast.IL.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("ArrayTypeD.", d1, d2); + } + + @Override + public DrawingTree visitBoolTypeDenoter(BoolTypeDenoter ast, Void obj) { + return layoutNullary("bool"); + } + + @Override + public DrawingTree visitCharTypeDenoter(CharTypeDenoter ast, Void obj) { + return layoutNullary("char"); + } + + @Override + public DrawingTree visitErrorTypeDenoter(ErrorTypeDenoter ast, Void obj) { + return layoutNullary("error"); + } + + @Override + public DrawingTree visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void obj) { + var d1 = ast.I.visit(this); + return layoutUnary("Sim.TypeD.", d1); + } + + @Override + public DrawingTree visitIntTypeDenoter(IntTypeDenoter ast, Void obj) { + return layoutNullary("int"); + } + + @Override + public DrawingTree visitRecordTypeDenoter(RecordTypeDenoter ast, Void obj) { + var d1 = ast.FT.visit(this); + return layoutUnary("Rec.TypeD.", d1); + } + + @Override + public DrawingTree visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + var d3 = ast.FT.visit(this); + return layoutTernary("Mult.F.TypeD.", d1, d2, d3); + } + + @Override + public DrawingTree visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.T.visit(this); + return layoutBinary("Sing.F.TypeD.", d1, d2); + } + + // Literals, Identifiers and Operators + @Override + public DrawingTree visitCharacterLiteral(CharacterLiteral ast, Void obj) { + return layoutNullary(ast.spelling); + } + + @Override + public DrawingTree visitIdentifier(Identifier ast, Void obj) { + return layoutNullary(ast.spelling); + } + + @Override + public DrawingTree visitIntegerLiteral(IntegerLiteral ast, Void obj) { + return layoutNullary(ast.spelling); + } + + @Override + public DrawingTree visitOperator(Operator ast, Void obj) { + return layoutNullary(ast.spelling); + } + + // Value-or-variable names + @Override + public DrawingTree visitDotVname(DotVname ast, Void obj) { + var d1 = ast.I.visit(this); + var d2 = ast.V.visit(this); + return layoutBinary("DotVname", d1, d2); + } + + @Override + public DrawingTree visitSimpleVname(SimpleVname ast, Void obj) { + var d1 = ast.I.visit(this); + return layoutUnary("Sim.Vname", d1); + } + + @Override + public DrawingTree visitSubscriptVname(SubscriptVname ast, Void obj) { + var d1 = ast.V.visit(this); + var d2 = ast.E.visit(this); + return layoutBinary("Sub.Vname", d1, d2); + } + + // Programs + @Override + public DrawingTree visitProgram(Program ast, Void obj) { + var d1 = ast.C.visit(this); + return layoutUnary("Program", d1); + } + + private DrawingTree layoutCaption(String name) { + var w = fontMetrics.stringWidth(name) + 4; + var h = fontMetrics.getHeight() + 4; + return new DrawingTree(name, w, h); + } + + private DrawingTree layoutNullary(String name) { + var dt = layoutCaption(name); + dt.contour.upper_tail = new Polyline(0, dt.height + 2 * BORDER, null); + dt.contour.upper_head = dt.contour.upper_tail; + dt.contour.lower_tail = new Polyline(-dt.width - 2 * BORDER, 0, null); + dt.contour.lower_head = new Polyline(0, dt.height + 2 * BORDER, dt.contour.lower_tail); + return dt; + } + + private DrawingTree layoutUnary(String name, DrawingTree d1) { + var dt = layoutCaption(name); + dt.setChildren(new DrawingTree[] { d1 }); + attachParent(dt, join(dt)); + return dt; + } + + private DrawingTree layoutBinary(String name, DrawingTree d1, DrawingTree d2) { + var dt = layoutCaption(name); + dt.setChildren(new DrawingTree[] { d1, d2 }); + attachParent(dt, join(dt)); + return dt; + } + + private DrawingTree layoutTernary(String name, DrawingTree d1, DrawingTree d2, DrawingTree d3) { + var dt = layoutCaption(name); + dt.setChildren(new DrawingTree[] { d1, d2, d3 }); + attachParent(dt, join(dt)); + return dt; + } + + private DrawingTree layoutQuaternary(String name, DrawingTree d1, DrawingTree d2, DrawingTree d3, DrawingTree d4) { + var dt = layoutCaption(name); + dt.setChildren(new DrawingTree[] { d1, d2, d3, d4 }); + attachParent(dt, join(dt)); + return dt; + } + + private void attachParent(DrawingTree dt, int w) { + var y = PARENT_SEP; + var x2 = (w - dt.width) / 2 - BORDER; + var x1 = x2 + dt.width + 2 * BORDER - w; + + dt.children[0].offset.y = y + dt.height; + dt.children[0].offset.x = x1; + dt.contour.upper_head = new Polyline(0, dt.height, new Polyline(x1, y, dt.contour.upper_head)); + dt.contour.lower_head = new Polyline(0, dt.height, new Polyline(x2, y, dt.contour.lower_head)); + } + + private int join(DrawingTree dt) { + + dt.contour = dt.children[0].contour; + var sum = dt.children[0].width + 2 * BORDER; + var w = sum; + + for (var i = 1; i < dt.children.length; i++) { + var d = merge(dt.contour, dt.children[i].contour); + dt.children[i].offset.x = d + w; + dt.children[i].offset.y = 0; + w = dt.children[i].width + 2 * BORDER; + sum += d + w; + } + return sum; + } + + private int merge(Polygon c1, Polygon c2) { + int x = 0, y = 0, total = 0; + var upper = c1.lower_head; + var lower = c2.upper_head; + + while (lower != null && upper != null) { + var d = offset(x, y, lower.dx, lower.dy, upper.dx, upper.dy); + x += d; + total += d; + + if (y + lower.dy <= upper.dy) { + x += lower.dx; + y += lower.dy; + lower = lower.link; + } else { + x -= upper.dx; + y -= upper.dy; + upper = upper.link; + } + } + + if (lower != null) { + var b = bridge(c1.upper_tail, 0, 0, lower, x, y); + c1.upper_tail = (b.link != null) ? c2.upper_tail : b; + c1.lower_tail = c2.lower_tail; + } else { + var b = bridge(c2.lower_tail, x, y, upper, 0, 0); + if (b.link == null) { + c1.lower_tail = b; + } + } + + c1.lower_head = c2.lower_head; + + return total; + } + + private int offset(int p1, int p2, int a1, int a2, int b1, int b2) { + + if (b2 <= p2 || p2 + a2 <= 0) { + return 0; + } + + var t = b2 * a1 - a2 * b1; + if (t > 0) { + if (p2 < 0) { + var s = p2 * a1; + return Math.max(0, s / a2 - p1); + } else if (p2 > 0) { + var s = p2 * b1; + return Math.max(0, s / b2 - p1); + } else { + return Math.max(0, -p1); + } + } else if (b2 < p2 + a2) { + var s = (b2 - p2) * a1; + return Math.max(0, b1 - (p1 + s / a2)); + } else if (b2 > p2 + a2) { + var s = (a2 + p2) * b1; + return Math.max(0, s / b2 - (p1 + a1)); + } else { + return Math.max(0, b1 - (p1 + a1)); + } + } + + private Polyline bridge(Polyline line1, int x1, int y1, Polyline line2, int x2, int y2) { + + int dx; + var dy = y2 + line2.dy - y1; + if (line2.dy == 0) { + dx = line2.dx; + } else { + var s = dy * line2.dx; + dx = s / line2.dy; + } + + var r = new Polyline(dx, dy, line2.link); + line1.link = new Polyline(x2 + line2.dx - dx - x1, 0, r); + + return r; + } + +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java new file mode 100644 index 0000000..d9bd6d0 --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polygon.java @@ -0,0 +1,20 @@ +/* + * @(#)Polygon.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +class Polygon { + Polyline lower_head, lower_tail; + Polyline upper_head, upper_tail; +} \ No newline at end of file diff --git a/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java new file mode 100644 index 0000000..546c37f --- /dev/null +++ b/Triangle.Compiler/src/main/java/triangle/treeDrawer/Polyline.java @@ -0,0 +1,29 @@ +/* + * @(#)Polyline.java 2.1 2003/10/07 + * + * Copyright (C) 1999, 2003 D.A. Watt and D.F. Brown + * Dept. of Computing Science, University of Glasgow, Glasgow G12 8QQ Scotland + * and School of Computer and Math Sciences, The Robert Gordon University, + * St. Andrew Street, Aberdeen AB25 1HG, Scotland. + * All rights reserved. + * + * This software is provided free for educational use only. It may + * not be used for commercial purposes without the prior written permission + * of the authors. + */ + +package triangle.treeDrawer; + +/** + * used to keep track of the position for components in the tree to be drawn + */ +class Polyline { + int dx, dy; + Polyline link; + + Polyline(int dx, int dy, Polyline link) { + this.dx = dx; + this.dy = dy; + this.link = link; + } +} diff --git a/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java b/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java new file mode 100644 index 0000000..ab10811 --- /dev/null +++ b/Triangle.Compiler/src/test/java/triangle/syntacticAnalyser/TestScanner.java @@ -0,0 +1,84 @@ +package triangle.syntacticAnalyser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; + +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +import triangle.ErrorReporter; +import triangle.syntacticAnalyzer.Parser; +import triangle.syntacticAnalyzer.Scanner; +import triangle.syntacticAnalyzer.SourceFile; + +public class TestScanner { + + @Test + public void testHi() { + compileExpectSuccess("/hi.tri"); + } + + + @Test + public void testHiNewComment() { + compileExpectFailure("/hi-newcomment.tri"); + } + + + @Test + public void testHiNewComment2() { + compileExpectFailure("/hi-newcomment2.tri"); + } + + + @Test + public void testBarDemo() { + compileExpectFailure("/bardemo.tri"); + } + + + @Test + public void testRepeatUntil() { + compileExpectFailure("/repeatuntil.tri"); + } + + + + private void compileExpectSuccess(String filename) { + // build.gradle has a line sourceSets.test.resources.srcDir file("$rootDir/programs") + // which adds the programs directory to the list of places Java can easily find files + // getResource() below searches for a file, which is in /programs + //SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString()); + SourceFile source = SourceFile.fromResource(filename); + + Scanner scanner = new Scanner(source); + ErrorReporter reporter = new ErrorReporter(true); + Parser parser = new Parser(scanner, reporter); + + parser.parseProgram(); + + // we should get to here with no exceptions + + assertEquals("Problem compiling " + filename, 0, reporter.getNumErrors()); + } + + private void compileExpectFailure(String filename) { + //SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString()); + SourceFile source = SourceFile.fromResource(filename); + Scanner scanner = new Scanner(source); + ErrorReporter reporter = new ErrorReporter(true); + Parser parser = new Parser(scanner, reporter); + + // we expect an exception here as the program has invalid syntax + assertThrows(RuntimeException.class, new ThrowingRunnable() { + public void run(){ + parser.parseProgram(); + } + }); + + // currently this program will fail + assertNotEquals("Problem compiling " + filename, 0, reporter.getNumErrors()); + } + +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..88279c3 --- /dev/null +++ b/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'java' + +sourceCompatibility = 11 + +subprojects.each { subproject -> + evaluationDependsOn(subproject.path) +} + +jar { + from subprojects.sourceSets.main.output +} \ No newline at end of file diff --git a/build/libs/Triangle-Tools.jar b/build/libs/Triangle-Tools.jar new file mode 100644 index 0000000000000000000000000000000000000000..3d2dbf79ceeb6869b256983fd789665a8383828a GIT binary patch literal 172601 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

evw(A}OZ7nfSXfDA4fVe{h2yJ+E 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 PgMW-c=GtTe4gdcGsarfp literal 0 HcmV?d00001 diff --git a/build/tmp/jar/MANIFEST.MF b/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e750102 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1b6c787 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/obj.tam b/obj.tam new file mode 100644 index 0000000000000000000000000000000000000000..26e8273394ea0093e3527aa8f5342c8302a0768d GIT binary patch literal 112 lcmZQzU|?oI01qIO4TzbbLZUz#Sw541ydoBPeyCYs3II>Z0YU%( literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..596a93b --- /dev/null +++ b/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + triangle.tools + triangle-tools + 2.1 + pom + + 17 + 17 + UTF-8 + + + Triangle.AbstractMachine + Triangle.Compiler + Triangle.AbstractMachine.Disassembler + Triangle.AbstractMachine.Interpreter + + \ No newline at end of file diff --git a/programs/adddeep.tri b/programs/adddeep.tri new file mode 100644 index 0000000..5f33bc1 --- /dev/null +++ b/programs/adddeep.tri @@ -0,0 +1,12 @@ +let + var a: Integer +in +begin + a := 10 + 20 * 2 / 3; + putint(a); + + puteol(); + + a := 5 + 8; + putint(a) +end diff --git a/programs/arrays.tam b/programs/arrays.tam new file mode 100644 index 0000000000000000000000000000000000000000..a3d0afefc417d19bb18736bb511ad923df25b6ac GIT binary patch literal 1376 zcmb`FO-=$q5QQ575hS`%3<)H709Uf`F2?&G!38nn`#N3Bqr!|EE2)`!T|fP*s!J*B z(#uZfs)uDFdusSo_O0}$ojtezo&J-q>wffi|5n)ZsW+3>_~!HbpHlom*y~-~*J7zj zy>jLLg^q(OafsK0AL4v6Uyr9==0BECEzhUd2NERkSxWuBFJX_T-+O7uxz~0;uFvmX zcx->9W&WQ3Mu22!9=RX*pE+s%-@?w{=O2CIN8mxO$G_l^4BemO|9c;=x_fNi^y~Bb zfUKnQZT&kwRd4U_S}e!RgL=NN{2u5x<|ebgWyjc#nW^J>!pz$J%+E1>IED{3QS1=M zzR$e^uI+Ou{@CKFOHAG`?;+Q7e$37>yK~I0sEcwQDznN)-|%xcHo`yp{i{EJFXTK@ GAmkUQcpjnv literal 0 HcmV?d00001 diff --git a/programs/arrays.tri b/programs/arrays.tri new file mode 100644 index 0000000..1cfbd28 --- /dev/null +++ b/programs/arrays.tri @@ -0,0 +1,47 @@ +let + type Vector ~ array 3 of Integer; + type Matrix ~ array 3 of Vector; + + proc putvector (v: Vector) ~ + let var i: Integer + in + begin + put ('['); putint (v[0]); + i := 1; + while i < 3 do + begin + put (' '); putint (v[i]); + i := i+1 + end; + put (']') + end; + + proc putmatrix (m: Matrix) ~ + let var i: Integer + in + begin + i := 0; + while i < 3 do + begin + putvector (m[i]); + puteol (); + i := i+1 + end + end; + + func diagonal + (m: Matrix): Vector ~ + [m[0][0], m[1][1], m[2][2]]; + + var me: Matrix + +in + begin + me := [[1,2,3], [4,5,6], [7,8,9]]; + putmatrix (me); puteol (); + putvector (diagonal (me)); + puteol (); puteol (); + me[1] := [10,11,12]; + me[1][1] := 22; + putmatrix (me); puteol () + end diff --git a/programs/assignments.tri b/programs/assignments.tri new file mode 100644 index 0000000..102bb78 --- /dev/null +++ b/programs/assignments.tri @@ -0,0 +1,9 @@ +let + var n : Integer; + var c : Char +in + + begin + c := '&'; + n := n + 1 + end diff --git a/programs/bank.tri b/programs/bank.tri new file mode 100644 index 0000000..e7f3c0f --- /dev/null +++ b/programs/bank.tri @@ -0,0 +1,86 @@ +let + const max ~ 9999; + const invalid ~ 0-1; + type Money ~ Integer; ! 0 .. max + type Trans ~ Char; ! 'd' | 'w' | 'q' + + func sum (m: Money, n: Money): Money ~ + let const s ~ m + n + in + if s <= max then s else invalid; + + func diff (m: Money, n: Money): Money ~ + let const d ~ m - n + in + if 0 <= d then d else invalid; + + proc gettrans (var code: Trans, + var amount: Money) ~ + begin + get(var code); + if code = 'q' then + ! skip + else + begin + getint(var amount); + if (0 > amount) \/ (amount > max) then + begin + amount := invalid; code := '?' + end + else if (code \= 'd') /\ (code \= 'w') then + code := '?' + else + ! ok + end; + geteol() + end; + + proc processtrans (code: Trans, + amount: Money, + var balance: Money) ~ + let + var newbalance: Money + in + begin + if code = 'd' then + begin + put('D'); put('e'); put('p'); put('o'); put('s'); + put('i'); put('t'); put(' '); + putint(amount); puteol(); + newbalance := sum(balance, amount) + end + else if code = 'w' then + begin + put('W'); put('i'); put('t'); put('h'); put('d'); + put('r'); put('a'); put('w'); put(' '); + putint(amount); puteol(); + newbalance := diff(balance, amount) + end + else + ; !skip + if (code = '?') \/ (newbalance = invalid) then + begin + put('I'); put('n'); put('v'); put('a'); put('l'); + put('i'); put('d'); puteol() + end + else + balance := newbalance; + put('B'); put('a'); put('l'); put('a'); put('n'); + put('c'); put('e'); put(' '); + putint(balance); puteol(); + end; + + var balance: Money; + var amount: Money; + var trans: Trans + +in + begin + balance := 0; + gettrans(var trans, var amount); + while trans \= 'q' do + begin + processtrans(trans, amount, var balance); + gettrans(var trans, var amount) + end + end diff --git a/programs/bardemo.tri b/programs/bardemo.tri new file mode 100644 index 0000000..f730f74 --- /dev/null +++ b/programs/bardemo.tri @@ -0,0 +1,19 @@ +! this won't work until after some work in the practicals +let + var a : Integer; + var b : Integer + +in + begin + a := 1; + b := 2; + + putint(a); + puteol(); + putint(b); + puteol(); + putint(|a); + puteol(); + putint(|b); + puteol() + end diff --git a/programs/control.tri b/programs/control.tri new file mode 100644 index 0000000..9d76146 --- /dev/null +++ b/programs/control.tri @@ -0,0 +1,26 @@ +! Plot a histogram from a stream of nonzero integers. + +let + const mark ~ '+'; + var n : Integer +in + begin + getint (var n); geteol (); + while n \= 0 do + let + var i : Integer; + var gap : Integer + in + begin + gap := if n > 0 then 20 else 20 + n; + if n < 0 then n := 0 - n else ; + i := 0; + while i < gap do + begin put (' '); i := i + 1 end; + i := 0; + while i < n do + begin put (mark); i := i + 1 end; + puteol (); + getint (var n); geteol () + end + end diff --git a/programs/deepnest.tri b/programs/deepnest.tri new file mode 100644 index 0000000..315b123 --- /dev/null +++ b/programs/deepnest.tri @@ -0,0 +1,16 @@ +let proc p1 () ~ + let var c1: Char; + proc p2 () ~ + let proc p3 () ~ + let proc p4 () ~ + let proc p5 () ~ + let proc p6 () ~ + let proc p7 () ~ + put (c1) + in p7 () + in p6 () + in p5 () + in p4 () + in p3 () + in begin c1 := '+'; p2 () end +in p1 () diff --git a/programs/directories.tri b/programs/directories.tri new file mode 100644 index 0000000..49e6794 --- /dev/null +++ b/programs/directories.tri @@ -0,0 +1,117 @@ +let + type Name ~ array 6 of Char; + type Number ~ Integer; + + proc prompt () ~ + begin + put('N'); put('a'); put('m'); put('e'); + put('?'); put(' ') + end; + + proc getname (var newname: Name) ~ + let var i: Integer + in + begin + i := 0; + while i < 6 do + begin + if eol () then + newname[i] := ' ' + else + get (var newname[i]); + i := i+1 + end + end; + + proc putname (newname: Name) ~ + let var i: Integer + in + begin + i := 0; + while i < 6 do + begin + put (newname[i]); + i := i+1 + end + end; + + type Entry ~ record + number: Number, + name: Name + end; + type Directory ~ record + size: Integer, + entry: array 100 of Entry + end; + + proc initialize (var dir: Directory) ~ + dir.size := 0; + + proc add (var dir: Directory, + newname: Name, + newnumber: Number) ~ + begin + dir.entry[dir.size] := + {number ~ newnumber, name ~ newname}; + dir.size := dir.size + 1 + end; + + proc lookup (var dir: Directory, + oldname: Name, + var oldnumber: Number, + var found: Boolean) ~ + let + var i: Integer; + var searching: Boolean + in + begin + i := 0; searching := true; + while (i < dir.size) /\ searching do + if dir.entry[i].name = oldname then + searching := false + else + i := i+1; + found := \searching; + if found then + oldnumber := dir.entry[i].number + else !skip + end; + + var mydir: Directory + +in + + begin + initialize (var mydir); + add (var mydir, + ['D','a','v','i','d',' '], 6041); + add (var mydir, + ['M','u','f','f','y',' '], 4969); + add (var mydir, + ['K','i','e','r','a','n'], 6042); + add (var mydir, + ['A','l','e','x','a',' '], 5322); + + let + const blank ~ [' ', ' ', ' ', ' ', ' ', ' ']; + var name: Name; + var num: Number; + var ok: Boolean + in + begin + prompt (); + getname (var name); geteol (); + while name \= blank do + begin + putname (name); put (' '); + lookup (var mydir, name, var num, var ok); + if ok then + putint (num) + else + put ('?'); + puteol (); + prompt (); + getname (var name); geteol () + end + end + end diff --git a/programs/errors.tri b/programs/errors.tri new file mode 100644 index 0000000..ed0e097 --- /dev/null +++ b/programs/errors.tri @@ -0,0 +1,30 @@ +! Program with a variety of contextual errors. + +let + type String ~ array 4 of Char; + type Name ~ array 3 of String; + type Rec ~ record x: Integer, x: Integer end; + + var me: Name; + var silly : maxint; + var silly: Rec; + + proc putstr (s: String) ~ + let var i: Integer + in + begin + s[4] := ' '; + i := 0; + while i do + begin i := i+true; + put (s[\i]) + end + end + +in + begin + me[true] := ['T','i','n','y']; + me[2][2] := 0; + put (me[1]); put (4); put (); + putstr (initials (me)); puteol () + end diff --git a/programs/every.tri b/programs/every.tri new file mode 100644 index 0000000..011fd1c --- /dev/null +++ b/programs/every.tri @@ -0,0 +1,148 @@ +! Marry a woman and man. +! Input following data for each person (woman then man): +! surname, forename (each up to 10 non-blank chars), +! sex ('M'|'F'), marital status ('m'|'u'), +! day, month, year of birth. + +let + type Month ~ Integer; + const Jan ~ 1; const Feb ~ 2; const Mar ~ 3; + const Apr ~ 4; const May ~ 5; const Jun ~ 6; + const Jul ~ 7; const Aug ~ 8; const Sep ~ 9; + const Oct ~ 10; const Nov ~ 11; const Dec ~ 12; + + type Date ~ record + y : Integer, + m : Month, + d : Integer + end; + const today ~ {y ~ 1993, m ~ Apr, d ~ 1}; + + proc getdate (var date : Date) ~ + begin + getint (var date.d); getint (var date.m); getint (var date.y) + end; + + proc putdate (date : Date) ~ + begin + putint (date.d); put ('/'); + putint (date.m); put ('/'); + putint (date.y // 100) + end; + + func yearsbefore (yrs : Integer, date : Date) : Date ~ + {y ~ date.y - yrs, m ~ date.m, d ~ date.d}; + + func earlier (date1 : Date, date2 : Date) : Boolean ~ + if date1.y < date2.y then true + else if date1.y > date2.y then false + else if date1.m < date2.m then true + else if date1.m > date2.m then false + else date1.d < date2.d; + + const maxname ~ 10; + type Name ~ array 10 of Char; + + proc getname (var name : Name) ~ + let + var ch : Char; + var length : Integer + in + begin + get (var ch); while ch = ' ' do get (var ch); + length := 0; + while length < maxname do + begin + length := length + 1; name[length] := ch; + if ch \= ' ' then get (var ch) else ! skip + end + end; + + proc putname (name : Name) ~ + let + var pad : Boolean; + var length : Integer + in + begin + pad := false; length := 0; + while (\ pad) /\ (length < maxname) do + begin + length := length + 1; + if name[length] = ' ' then + pad := true + else + put (name[length]) + end + end; + + type Person ~ record + surname : Name, + forename : Name, + male : Boolean, + married : Boolean, + dob : Date + end; + + proc getperson (var person : Person) ~ + let + var fore : Name; + var sur : Name; + var s : Char; + var m : Char; + var birth : Date + in + begin + getname (var sur); getname (var fore); + get (var s); while s = ' ' do get (var s); + get (var m); while m = ' ' do get (var m); + getdate (var birth); + person := {surname ~ sur, forename ~ fore, + male ~ (s = 'M'), married ~ (m = 'm'), + dob ~ birth} + end; + + proc putperson (person : Person) ~ + begin + putname (person.surname); put (' '); + putname (person.forename); put (' '); + put (if person.male then 'M' else 'F'); put (' '); + put (if person.married then 'm' else 'u'); put (' '); + putdate (person.dob) + end; + + func age (person : Person) : Integer ~ + let + const dob ~ person.dob + in + if (today.m > dob.m) \/ + ((today.m = dob.m) /\ (today.d >= dob.d)) + then today.y - dob.y + else today.y - dob.y - 1; + + const latestdob ~ yearsbefore (16, today); + + var bride : Person; + var groom : Person + +in + begin + getperson (var bride); + getperson (var groom); + puteol (); + if \ bride.male /\ groom.male /\ + \ (bride.married \/ groom.married) /\ + \ earlier (latestdob, bride.dob) /\ + \ earlier (latestdob, groom.dob) then + begin + put ('O'); put ('K'); puteol (); + bride.married := true; groom.married := true; + bride.surname := groom.surname + end + else + begin + put ('N'); put ('o'); put ('!'); puteol () + end; + putperson (bride); put (' '); putint (age (bride)); puteol (); + putperson (groom); put (' '); putint (age (groom)); puteol (); + putdate (today); puteol () + end diff --git a/programs/factorials.tri b/programs/factorials.tri new file mode 100644 index 0000000..c1db33c --- /dev/null +++ b/programs/factorials.tri @@ -0,0 +1,15 @@ +let + func factorial (n: Integer): Integer ~ + if n <= 1 + then 1 + else n * factorial (n-1); + + var i: Integer + +in + begin + getint (var i); + putint (i); put ('!'); + put (' '); put ('='); put (' '); + putint (factorial (i)) + end diff --git a/programs/functions.tri b/programs/functions.tri new file mode 100644 index 0000000..d343874 --- /dev/null +++ b/programs/functions.tri @@ -0,0 +1,28 @@ +! Print powers of integers. + +let + func even (n : Integer) : Boolean ~ + (n // 2) = 0; + + func sqr (n : Integer) : Integer ~ + n * n; + + func power (b : Integer, n : Integer) : Integer ~ + ! assume n >= 0 + if n = 0 + then 1 + else + if even (n) + then sqr (power (b, n/2)) + else sqr (power (b, n/2)) * b; + + var x : Integer; + var m : Integer +in + begin + getint (var x); getint (var m); + putint (x); put ('^'); putint (m); + put (' '); put ('='); put (' '); + putint (power (x, m)); + puteol () + end diff --git a/programs/hi-newcomment.tri b/programs/hi-newcomment.tri new file mode 100644 index 0000000..0929f38 --- /dev/null +++ b/programs/hi-newcomment.tri @@ -0,0 +1,7 @@ +! this won't work until after some work in the practicals + +# new comment + +begin + put('H'); put('i'); put('!') +end diff --git a/programs/hi-newcomment2.tri b/programs/hi-newcomment2.tri new file mode 100644 index 0000000..4e764fc --- /dev/null +++ b/programs/hi-newcomment2.tri @@ -0,0 +1,11 @@ +! this won't work until after some work in the practicals + +# new comment + +$ +another new comment +$ + +begin + put('H'); put('i'); put('!') +end diff --git a/programs/hi.tam b/programs/hi.tam new file mode 100644 index 0000000000000000000000000000000000000000..26e8273394ea0093e3527aa8f5342c8302a0768d GIT binary patch literal 112 lcmZQzU|?oI01qIO4TzbbLZUz#Sw541ydoBPeyCYs3II>Z0YU%( literal 0 HcmV?d00001 diff --git a/programs/hi.tri b/programs/hi.tri new file mode 100644 index 0000000..aac4ec1 --- /dev/null +++ b/programs/hi.tri @@ -0,0 +1,3 @@ +begin + put('H'); put('i'); put('!') +end diff --git a/programs/hullo.tri b/programs/hullo.tri new file mode 100644 index 0000000..a7a40a0 --- /dev/null +++ b/programs/hullo.tri @@ -0,0 +1,53 @@ +let + const maxlength ~ 15; + type String ~ array 16 of Char; + const null ~ chr(0); +!Strings will be padded with nulls. + + proc getstring (var s: String) ~ + let var l: Integer + in + begin + l := 0; + while l < maxlength do + begin + if eol () then + s[l] := null + else + get (var s[l]); + l := l+1; + end; + s[maxlength] := null + end; + + proc putstring (s: String) ~ + let var i: Integer + in + begin + i := 0; + while s[i] \= null do + begin + put (s[i]); + i := i+1 + end + end; + + var you: String + +in + begin + putstring ( + ['W','h','o',' ', + 'a','r','e',' ', + 'y','o','u','?', + null,null,null,null]); + puteol (); + getstring (var you); geteol (); + putstring ( + ['H','u','l','l', + 'o',',',' ',null, + null,null,null,null, + null,null,null,null]); + putstring (you); put ('!'); + puteol () +end diff --git a/programs/ifdemo.tri b/programs/ifdemo.tri new file mode 100644 index 0000000..ddc4df3 --- /dev/null +++ b/programs/ifdemo.tri @@ -0,0 +1,9 @@ +let + var a : Integer; + var n : Integer +in + begin + if a < 0 + then n := 0 + else n := 1 + end diff --git a/programs/increment.tri b/programs/increment.tri new file mode 100644 index 0000000..11358a5 --- /dev/null +++ b/programs/increment.tri @@ -0,0 +1,14 @@ +! this won't compile without implementing the bonus material in Practical 3 + +let + var a: Integer +in +begin + getint(var a); + a++; + putint(a); + puteol(); + a++; + putint(a); + puteol(); +end diff --git a/programs/names.tri b/programs/names.tri new file mode 100644 index 0000000..741167a --- /dev/null +++ b/programs/names.tri @@ -0,0 +1,52 @@ +let + type Name ~ array 6 of Char; + type Number ~ Integer; + + proc getname (var newname: Name) ~ + let var i: Integer + in + begin + i := 0; + while i < 6 do + begin + if eol () then + newname[i] := ' ' + else + get (var newname[i]); + i := i+1 + end + end; + + proc putname (newname: Name) ~ + let var i: Integer + in + begin + i := 0; + while i < 6 do + begin + put (newname[i]); + i := i+1 + end + end; + + func samename (name1: Name, name2: Name) : Boolean ~ + let + func same (n: Integer) : Boolean ~ + (name1[n] = name2[n]) /\ + (if n = 0 then true else same (n-1)) + in + same (5); + + var nam: Name + +in + + begin + getname (var nam); geteol (); + putname (nam); put (' '); + if samename (nam, ['D','a','v','i','d',' ']) then + put ('Y') + else + put ('N'); + puteol () + end diff --git a/programs/nesting.tri b/programs/nesting.tri new file mode 100644 index 0000000..90838ca --- /dev/null +++ b/programs/nesting.tri @@ -0,0 +1,31 @@ +let + var g: Integer; + + proc P() ~ + let + var p: Integer; + + proc Q() ~ + let + var q: Integer; + proc R() ~ + let + var r: Integer + in + r := (g+p+q) * 1000 ! should cause overflow + in + begin q := g+p; R() end; + + proc S() ~ + let + var s: Integer + in + begin s := g+p+1; Q() end + + in + begin p := g+1; S() end + +in + begin g := 1000; P() end + + diff --git a/programs/procedural.tri b/programs/procedural.tri new file mode 100644 index 0000000..65263d0 --- /dev/null +++ b/programs/procedural.tri @@ -0,0 +1,56 @@ +! test program proc.Æ +let + const size ~ 6; + type String ~ array 6 of Char; + + proc putstr (s: String) ~ + let var i: Integer + in + begin + i := 0; + while i < size do + begin put (s[i]); i := i+1 end + end; + + proc apply (proc p (var c : Char), var s : String) ~ + let + var i : Integer + in + begin + i := 0; + while i < size do + begin + p (var s[i]); + i := i+1 + end + end; !apply + + proc shift (var l : Char) ~ + let const ordl ~ ord (l) + in + if (ord('a') <= ordl) + /\ (ordl <= ord('z')) then + l := chr (ordl - ord('a') + ord('A')) + else + ; !skip + + proc replaceall (old: Char, new: Char, + var s: String) ~ + let + proc zap (var c: Char) ~ + if c = old then c := new else !skip + in + apply (proc zap, var s); + + var name : String + +in + begin + apply (proc get, var name); + geteol (); + putstr (name); puteol (); + apply (proc shift, var name); + putstr (name); puteol (); + replaceall ('I', 'i', var name); + putstr (name); puteol () + end diff --git a/programs/procedures.tri b/programs/procedures.tri new file mode 100644 index 0000000..a72f68c --- /dev/null +++ b/programs/procedures.tri @@ -0,0 +1,31 @@ +! Plot a histogram from a stream of nonzero integers. + +let + const mid ~ 40; + var n : Integer; + + proc putmany (c : Char, n : Integer) ~ + let + var i : Integer + in + begin + i := 0; + while i < n do + begin put (c); i := i + 1 end + end; + + proc makenonnegative (var n : Integer) ~ + if n < 0 then n := 0 - n else + +in + begin + getint (var n); geteol (); + while n \= 0 do + begin + putmany (' ', if n > 0 then mid else mid + n); + makenonnegative (var n); + putmany ('+', n); + puteol (); + getint (var n); geteol () + end + end diff --git a/programs/records.tri b/programs/records.tri new file mode 100644 index 0000000..5d8f63e --- /dev/null +++ b/programs/records.tri @@ -0,0 +1,24 @@ +! test program record.Æ +let + type Month ~ array 3 of Char; + type Date ~ record d: Integer, m: Month end; + const xmas ~ {d ~ 25, + m ~ ['D','e','c']}; + var eve: Date; + + proc putmonth (mth: Month) ~ + begin + put (mth[0]); put (mth[1]); put (mth[2]) + end; + + proc putdate (date: Date) ~ + begin + putint (date.d); put ('/'); putmonth (date.m) + end + +in + begin + putdate (xmas); puteol (); + eve := {d ~ xmas.d-1, m ~ xmas.m}; + putdate (eve); puteol () + end \ No newline at end of file diff --git a/programs/repeatuntil.tri b/programs/repeatuntil.tri new file mode 100644 index 0000000..c2518de --- /dev/null +++ b/programs/repeatuntil.tri @@ -0,0 +1,14 @@ +! this won't work until after some lab work + +let + var a : Integer +in +begin + a := 0; + repeat + begin + put('a'); + a := a + 1; + end + until a >= 5 +end diff --git a/programs/repl.tri b/programs/repl.tri new file mode 100644 index 0000000..f6cf367 --- /dev/null +++ b/programs/repl.tri @@ -0,0 +1,13 @@ +let + type Str ~ array 10 of Char; + + func replicate (c: Char): Str ~ + [c,c,c,c,c,c,c,c,c,c]; + + var s: Str +in + + begin + s := replicate('*'); + put (s[0]); put(s[9]); puteol() + end diff --git a/programs/run b/programs/run new file mode 100755 index 0000000..84ed354 --- /dev/null +++ b/programs/run @@ -0,0 +1,43 @@ +#!/bin/bash + +# Term colours for output +RED='\033[0;31m' # Red +GRN='\033[0;32m' # Green +NC='\033[0m' # No Color + +TRI="" + +# Check if the input in arg 1 ($1) is empty +if [ -z "$1" ] + then # if empty... + printf "${RED}Usage: $0 *.tri file (optional: $0 *.tri tree)${NC}" + exit 1 # Exit with code 1, failure + else + TRI=$1 +fi + +#Remove the extension of the file +FILENAME=$(echo $TRI | cut -f 1 -d '.') + +#TODO: implement tree command +printf "${GRN}[INFO] Compiling file: $FILENAME.tri to $FILENAME.tam ...${NC}\n" + +# Compile to tam +if java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri -o=$FILENAME.tam &> /dev/null #quiet + then if [ -z "$2" ] + then #if empty + printf "${GRN}[INFO] Running file: $FILENAME.tam ...${NC}\n" + java -cp ../build/libs/Triangle-Tools.jar triangle.abstractMachine.Interpreter $FILENAME.tam + exit 0 + else + printf "${GRN}[INFO] Running file: $FILENAME.tam ... and displaying AST${NC}\n" + java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri tree -o=$FILENAME.tam &> /dev/null #quiet + exit 0 + fi + + else + printf "${RED}[ERROR] Could not complie $FILENAME.tri ...${NC}" + err=$(java -cp ../build/libs/Triangle-Tools.jar triangle.Compiler $FILENAME.tri -o=$FILENAME.tam) + printf "${RED}\n$err\n${NC}" + exit 1 +fi diff --git a/programs/simpleadding.tri b/programs/simpleadding.tri new file mode 100644 index 0000000..139847a --- /dev/null +++ b/programs/simpleadding.tri @@ -0,0 +1,10 @@ +let + var a : Integer; + var b : Integer; + var c : Integer + +in + begin + a := 1; b := 2; c := a / b; + end + diff --git a/programs/triangle.tam b/programs/triangle.tam new file mode 100644 index 0000000000000000000000000000000000000000..87d30f3a2fdcd7e2e56f4950ec90af4c3148c56f GIT binary patch literal 1056 zcmb`GL2g1Z3`7H^r9cH@K?^(1Krg`k4+YFaH9T2eGLj`bo|!nw|6`1=@x(Ui@>z~a z@;B9_v&3hjde*NX1nygp<|8qM6wDLdkM+C$8YDM=M>DYhqYnL&!hB|1LkQUWJyA2( z8eRqF>gVq@KFnP3e)}xC{!Z=lqd`mHL-_uFQv>&{hj0J7Kl8082ku+X+3kN!O&^rT z{d3l>ulFb}^O?_mn$KI*dn6sFMCY?^KkFBbkJkNHoX79MeD?oI4LqM~a-XNa7xUS# hf1ih@um7a>!{7RTAOG#=dCq@&e9F`R1N&`g7H)LV4AlSt literal 0 HcmV?d00001 diff --git a/programs/triangle.tri b/programs/triangle.tri new file mode 100644 index 0000000..555ea81 --- /dev/null +++ b/programs/triangle.tri @@ -0,0 +1,32 @@ +let + + proc putmany (n: Integer, c: Char) ~ + let + var i: Integer + in + begin + i := 0; + while i < n do + begin i := i+1; put (c) end + end; + + var n: Integer; var r: Integer; + const mark ~ '@' + +in + begin + getint (var n); geteol (); + r := 0; + while r < (n-1) do + begin + r := r + 1; + putmany (n-r, ' '); put (mark); + if r >= 2 then + begin + putmany (2*r - 3, ' '); put (mark) + end + else; !skip + puteol () + end; + putmany (2*n - 1, mark) + end diff --git a/programs/while-longloop.tri b/programs/while-longloop.tri new file mode 100644 index 0000000..75b1088 --- /dev/null +++ b/programs/while-longloop.tri @@ -0,0 +1,22 @@ +let + var a : Integer; + var b : Integer; + var c : Integer +in +begin + put('1'); + puteol(); + a := 0; + while a < 5000 do + begin + b := 0; + while b < 3000 do + begin + c := c + a; + c := c / (1 + b); + b := b + 1; + end; + a := a + 1; + end; + putint(c); +end diff --git a/programs/while.tri b/programs/while.tri new file mode 100644 index 0000000..9bbb664 --- /dev/null +++ b/programs/while.tri @@ -0,0 +1,11 @@ +let + var a : Integer +in +begin + a := 0; + while a < 5 do + begin + put('a'); + a := a + 1; + end +end diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..5e273cd --- /dev/null +++ b/settings.gradle @@ -0,0 +1,7 @@ +rootProject.name = 'Triangle-Tools' + +include 'Triangle.Compiler' +include 'Triangle.AbstractMachine' +include 'Triangle.AbstractMachine.Disassembler' +include 'Triangle.AbstractMachine.Interpreter' +